php / php/php-src

json_decode() fails on nested input of around 10000 characters.

未关闭
#10,104 6 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Extension: json Status: Needs Triage
主要语言
C
星标
40.4k
派生
8.1k
平均合并
2 天 13 小时
30 天内合并 PR
96

描述

Description

The following code:

<?php

function test($i, $s) {
  try {
    json_decode($s, false, 999999999, JSON_THROW_ON_ERROR);
    echo "Test $i passed\n";
  } catch (Exception $e) {
    echo "Test $i FAILED: $e\n";
  }
}

// String like [[[[...1...]]]] fails at length 9999, nesting depth 4999.
test(1, str_repeat('[', 4998) . '1' . str_repeat(']', 4998)); // pass
test(2, str_repeat('[', 4999) . '1' . str_repeat(']', 4999)); // FAIL

// String like [1,[1,[1,...1...]]] fails at length 10001, nesting depth 2499.
test(3, str_repeat('[1,', 2499) . '1' . str_repeat(']', 2499)); // pass
test(4, str_repeat('[1,', 2500) . '1' . str_repeat(']', 2500)); // FAIL

// Flat string like [[1],[1],[1]...] passes even at much greater length.
test(5, '[' . str_repeat('[1],', 9999) . '1]'); // pass

?>

Resulted in this output:

Test 1 passed
Test 2 FAILED: JsonException: Syntax error in json_decode_bug.php:5
Stack trace:
#0 json_decode_bug.php(5): json_decode()
#1 json_decode_bug.php(14): test()
#2 {main}
Test 3 passed
Test 4 FAILED: JsonException: Syntax error in json_decode_bug.php:5
Stack trace:
#0 json_decode_bug.php(5): json_decode()
#1 json_decode_bug.php(18): test()
#2 {main}
Test 5 passed

(I've removed the directory names from the stack trace for brevity.)

But I expected this output instead:

Test 1 passed
Test 2 passed
Test 3 passed
Test 4 passed
Test 5 passed

Note that the exception message ("Syntax error') is different from what I get when I reduce the maximum depth argument from 999999999 to 999. Then I get JsonException: Maximum stack depth exceeded instead (which is expected).

So it looks like the parser hits an undocumented limit when the input string reaches 10,000 characters, but only for the heavily-nested input.

PHP Version

PHP 8.1.13

Operating System

Arch Linux (x86_64)

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先在 PHP 8.1.13 上运行提供的 json_decode() 复现,并按照所示改变嵌套深度和最大深度参数。调查长度约为 10,000 个字符的深度嵌套输入的解析器行为;完成的标准是有效的嵌套输入能够成功解码,而真正过大的深度仍然报告预期的最大堆栈深度错误。

由索引模型根据 Issue 内容生成。

评估

技术栈
php
领域
backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。