)]}'
{
  "commit": "8519b8381f3c741ad1421f88237b1deda0b11412",
  "tree": "b2b54358d63493c3ea3d3e3c32719e8172c7035a",
  "parents": [
    "d4d072177213b117fb81d4cfda140de090616161"
  ],
  "author": {
    "name": "Helmut Januschka",
    "email": "helmut@januschka.com",
    "time": "Sun Jun 14 05:16:10 2026 +0200"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Sat Jun 13 20:16:10 2026 -0700"
  },
  "message": "fix: avoid quadratic re-scan of comments after a value (#1689)\n\n* fix: avoid quadratic re-scan of comments after a value\n\nOurReader::readComment() decides whether a comment should be attached to\nthe previous value (commentAfterOnSameLine) by scanning the input from the\nend of that value up to the comment with containsNewLine(). lastValueEnd_\nonly advances when a new value is read, so a long run of comments after a\nvalue (e.g. during error recovery, or a value followed by many comments)\nmade every comment re-scan the same growing prefix, giving O(n^2) parse\ntime. A jsoncpp_fuzzer testcase took ~18s for a 400KB input.\n\nA comment can only ever be on the same line as the last value if no\nnewline separates them, and the gap to inspect only grows as further\ncomments are consumed, so once the gap has been examined for the first\ncomment it never needs to be examined again. Mark lastValueHasAComment_\nafter the first comment following a value so subsequent comments skip the\nscan. Parsing the testcase drops from ~18s to ~56ms with identical output.\n\nAdd a regression test that parses a value followed by a large number of\ntrailing comments and requires it to complete well under a generous time\nbound.\n\n* test: assert linear comment scanning deterministically\n\nReplace the wall-clock bound in the comment regression test with a\ndirect, deterministic assertion on work done. The parse output is\nidentical with and without the fix, so the only observable difference is\nhow much the parser scans; a time bound is also flaky under\nvalgrind/sanitizers/loaded CI.\n\nAdd an instrumentation counter for the bytes examined by\nOurReader::containsNewLine, exposed via a JSON_API seam, and assert it\nstays linear in the input (scanned \u003c 4 * doc.size()) rather than\nO(comments * gap). The counter is thread_local (no race during\nconcurrent parsing) and the increment is negligible, running only while\nparsing comments. It is compiled unconditionally because the ABI\ncompatibility job builds the test suite against a separately-installed\nRelease library, so the symbol must exist there. Rename the test to\nparseCommentsAfterValueScansLinearly to describe what it checks, and\nlink crbug.com/521541633.\n\nVerified: the test fails when the fix is reverted and passes with it, in\nDebug and Release, and the seam links against a Release-installed shared\nlibrary (the ABI compatibility scenario).\n\n---------\n\nCo-authored-by: Jordan Bayles \u003cjophba@chromium.org\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "83743f73b4009d3c39f85e2a6f7c53eaab318e09",
      "old_mode": 33188,
      "old_path": "src/lib_json/json_reader.cpp",
      "new_id": "39ebcc6b5960fa8cb5ed4d5359bba9504501c4ed",
      "new_mode": 33188,
      "new_path": "src/lib_json/json_reader.cpp"
    },
    {
      "type": "modify",
      "old_id": "08731f66a394f53c8b8041e3c2ebf3333302b8e4",
      "old_mode": 33188,
      "old_path": "src/test_lib_json/main.cpp",
      "new_id": "9d13fdbe453a1fb615c71b7cfcc2c4a3957fd60a",
      "new_mode": 33188,
      "new_path": "src/test_lib_json/main.cpp"
    }
  ]
}
