Commit 8ab2340b8e2 for php

commit 8ab2340b8e20e5845f35069f41212a18142f57cc
Author: Yuma Kakei <yumasansansan@gmail.com>
Date:   Fri Oct 30 19:04:57 2026 +0900

    Check json_validate() in the JSON fuzzer (#24723)

    json_validate() uses its own parser methods and was not fuzzed at all.
    Check that it agrees with decoding to arrays, which, unlike decoding to
    objects, does not reject property names starting with a NUL byte.

diff --git a/sapi/fuzzer/fuzzer-json.c b/sapi/fuzzer/fuzzer-json.c
index 0407a895835..7ffa28df245 100644
--- a/sapi/fuzzer/fuzzer-json.c
+++ b/sapi/fuzzer/fuzzer-json.c
@@ -27,6 +27,10 @@
 #include "ext/json/php_json.h"
 #include "ext/json/php_json_parser.h"

+/* Lower than the default depth of 512, so that deeply nested inputs fail quickly and the
+ * depth limit is reached with small inputs. */
+#define MAX_DEPTH 10
+
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {

 	if (fuzzer_request_startup() == FAILURE){
@@ -55,10 +59,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
 	for (int index = 0; index < 12; ++index) {
 		zval result;
 		php_json_parser parser;
-		php_json_parser_init(&parser, &result, data, Size, options[index], 10);
-		if (php_json_yyparse(&parser) == SUCCESS) {
+		php_json_parser_init(&parser, &result, data, Size, options[index], MAX_DEPTH);
+		bool decoded = php_json_yyparse(&parser) == SUCCESS;
+		if (decoded) {
 			zval_ptr_dtor(&result);
 		}
+
+		/* json_validate() must agree with json_decode(). Only compare when decoding to arrays,
+		 * as decoding to objects additionally rejects property names starting with a NUL byte. */
+		if (options[index] == PHP_JSON_OBJECT_AS_ARRAY
+				|| options[index] == (PHP_JSON_OBJECT_AS_ARRAY | PHP_JSON_INVALID_UTF8_IGNORE)) {
+			bool valid = php_json_validate_ex(data, Size,
+				options[index] & PHP_JSON_INVALID_UTF8_IGNORE, MAX_DEPTH);
+			ZEND_ASSERT(valid == decoded);
+		}
 	}

 	php_request_shutdown(NULL);