Skip to content

Add defensive ChildCount() guards in parseMain to prevent AST index-out-of-bounds panics#20

Closed
Copilot wants to merge 3 commits intoUpdate-packagesfrom
copilot/sub-pr-19
Closed

Add defensive ChildCount() guards in parseMain to prevent AST index-out-of-bounds panics#20
Copilot wants to merge 3 commits intoUpdate-packagesfrom
copilot/sub-pr-19

Conversation

Copy link

Copilot AI commented Mar 6, 2026

parseMain accessed child.Child(1).Child(1) and statement.Child(2) without verifying child counts, risking panics on malformed or unexpected AST shapes (e.g., syntax errors, non-standard comparison forms).

Changes

  • python/file_parser.go: Added child.Child(1).ChildCount() > 2 guard before accessing the comparison operator's children. Since statement aliases child.Child(1), this single check also covers the statement.Child(0) and statement.Child(2) accesses downstream.
// Before
child.Child(1).Type() == sitterNodeTypeComparisonOperator &&
child.Child(1).Child(1).Type() == "==" {  // ← unguarded index into comparison node

// After
child.Child(1).Type() == sitterNodeTypeComparisonOperator &&
child.Child(1).ChildCount() > 2 &&        // ← guards .Child(1) and .Child(2)
child.Child(1).Child(1).Type() == "==" {

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

ewianda and others added 2 commits February 20, 2026 17:33
Migrate the Python file parser from recursive AST traversal to
pre-compiled tree-sitter queries, add object pooling, and batch-parse
all files into a lookup table to eliminate redundant work.

Changes:
- file_parser.go: Replace recursive parse() with query-based approach
  using pre-compiled tree-sitter queries (init-time), sync.Pool for
  parser and cursor reuse, and TYPE_CHECKING block detection.
- parser.go: Add parseAllToLUT() for concurrent batch parsing with
  errgroup limited to NumCPU, and parseFromLUT() to process pre-parsed
  results without re-parsing.
- generate.go: Parse all .py files once upfront into a LUT before
  target generation. Replace per-target parser.parse() calls with
  parseFromLUT() lookups. Replace per-call regexp.MustCompile in
  isDjangoTestFile with strings.Contains.

Profiled on production codebase (cpu pprof):

  | Metric      | Before  | After   | Improvement |
  |-------------|---------|---------|-------------|
  | Wall time   | 46.72s  | 13.25s  | 3.5x faster |
  | CPU samples | 53.04s  | 31.69s  | 40% less    |
  | cgocall     | 28.13s  | 23.68s  | 16% less    |

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nexpected AST shapes

Co-authored-by: ewianda <7077790+ewianda@users.noreply.github.com>
Copilot AI changed the title [WIP] Update package based on feedback from PR #19 review Add defensive ChildCount() guards in parseMain to prevent AST index-out-of-bounds panics Mar 6, 2026
@ewianda ewianda closed this Mar 9, 2026
@ewianda ewianda deleted the copilot/sub-pr-19 branch March 9, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants