From 93b47d5ee528d99ee4c4bcc15742fe21cf1f521a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 12:45:38 +0000 Subject: [PATCH 1/3] fix(runtime/explicit): prevent IndexError when << appears in default constructor args When a constructor has a default parameter value containing the bitwise left-shift operator (e.g. `A(int b, int c, int a = 1 << 1)`), the argument-collapsing loop in CheckForNonStandardConstructs crashed with IndexError because the two '<' characters in '<<' were counted as unmatched template angle brackets, causing the code to seek a non-existent next element. Fix by stripping '<<' occurrences before counting '<' and '>' for bracket-balance detection, and add an explicit bounds guard so that a malformed argument list cannot produce an out-of-range access. Adds a regression test for the exact snippet reported in issue #223. Fixes #223 https://claude.ai/code/session_01Ey7pVULvYhZPH5Unf1ZNe1 --- cpplint.py | 10 ++++++++-- cpplint_unittest.py | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cpplint.py b/cpplint.py index 86c1027..89462fa 100755 --- a/cpplint.py +++ b/cpplint.py @@ -3972,11 +3972,17 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, i = 0 while i < len(constructor_args): constructor_arg = constructor_args[i] - while constructor_arg.count("<") > constructor_arg.count(">") or constructor_arg.count( + # Strip << (bitwise left-shift) before counting angle brackets, to + # avoid confusing shift operators with unmatched template brackets. + cleaned_arg = re.sub(r"<<", "", constructor_arg) + while cleaned_arg.count("<") > cleaned_arg.count(">") or cleaned_arg.count( "(" - ) > constructor_arg.count(")"): + ) > cleaned_arg.count(")"): + if i + 1 >= len(constructor_args): + break constructor_arg += "," + constructor_args[i + 1] del constructor_args[i + 1] + cleaned_arg = re.sub(r"<<", "", constructor_arg) constructor_args[i] = constructor_arg i += 1 diff --git a/cpplint_unittest.py b/cpplint_unittest.py index 1066907..428b8a7 100755 --- a/cpplint_unittest.py +++ b/cpplint_unittest.py @@ -1805,6 +1805,15 @@ class Foo { """ class Foo { explicit Foo(int f, int g); + };""", + "", + ) + # No crash or warning for constructors with << (bitwise shift) in + # default parameter values (regression test for issue #223) + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = 1 << 1) {} };""", "", ) From f7cb5b33974307f5c77fb793a0b628cb2d88b166 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 12:52:21 +0000 Subject: [PATCH 2/3] fix(runtime/explicit): extend < -operator fix to cover <= and <<= as well The previous fix only stripped '<<' before bracket-balance counting. Any other operator that starts with '<' (specifically '<=' and the compound '<<=') also contributes a spurious '<' to the count, causing the arg-collapsing loop to incorrectly merge the following constructor argument (or, if there is none, to raise an IndexError without the bounds check). Changes: * Replace the single-pattern re.sub(r"<<") with a compiled regex that strips '<<=', '<=', and '<<' in longest-first order so that compound operators are matched whole rather than partially. * Move the compiled regex object above the outer while-loop so it is created once per call rather than once per argument. * Add regression tests for '<<=' and '<=' default-value cases. Note: '>>' and '>=' are intentionally left alone because an excess '>' count never triggers the joining loop, and stripping '>>' would break nested-template counting (e.g. vector>). https://claude.ai/code/session_01Ey7pVULvYhZPH5Unf1ZNe1 --- cpplint.py | 17 ++++++++++++----- cpplint_unittest.py | 21 +++++++++++++++++++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/cpplint.py b/cpplint.py index 89462fa..9ed4e08 100755 --- a/cpplint.py +++ b/cpplint.py @@ -3968,13 +3968,20 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, constructor_args = explicit_constructor_match.group(2).split(",") # collapse arguments so that commas in template parameter lists and function - # argument parameter lists don't split arguments in two + # argument parameter lists don't split arguments in two. + # Strip operator sequences that begin with '<' before counting angle + # brackets, to avoid confusing operators with unmatched template + # brackets. Longer sequences must come first so that '<<=' is not + # partially matched as '<<' leaving a stray '='. + # Note: '>>' and '>=' are intentionally left alone because extra '>' + # characters do not trigger the joining loop (condition is + # count('<') > count('>')), and stripping '>>' would break nested + # template types such as vector>. + _LANGLE_OPS_RE = re.compile(r"<<=|<=|<<") i = 0 while i < len(constructor_args): constructor_arg = constructor_args[i] - # Strip << (bitwise left-shift) before counting angle brackets, to - # avoid confusing shift operators with unmatched template brackets. - cleaned_arg = re.sub(r"<<", "", constructor_arg) + cleaned_arg = _LANGLE_OPS_RE.sub("", constructor_arg) while cleaned_arg.count("<") > cleaned_arg.count(">") or cleaned_arg.count( "(" ) > cleaned_arg.count(")"): @@ -3982,7 +3989,7 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, break constructor_arg += "," + constructor_args[i + 1] del constructor_args[i + 1] - cleaned_arg = re.sub(r"<<", "", constructor_arg) + cleaned_arg = _LANGLE_OPS_RE.sub("", constructor_arg) constructor_args[i] = constructor_arg i += 1 diff --git a/cpplint_unittest.py b/cpplint_unittest.py index 428b8a7..8016db4 100755 --- a/cpplint_unittest.py +++ b/cpplint_unittest.py @@ -1808,12 +1808,29 @@ class Foo { };""", "", ) - # No crash or warning for constructors with << (bitwise shift) in - # default parameter values (regression test for issue #223) + # No crash or warning for constructors with '<'-containing operators + # in default parameter values (regression test for issue #223). + # left shift << self.TestMultiLineLint( """ class A { A(int b, int c, int a = 1 << 1) {} + };""", + "", + ) + # compound left-shift-assign <<= + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = (x <<= 1)) {} + };""", + "", + ) + # less-or-equal <= + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = b <= c ? 1 : 0) {} };""", "", ) From 1489d3e873c06535914451c46d2de67f3dff3e93 Mon Sep 17 00:00:00 2001 From: ravenCrown0627 <60862845+ravenCrown0627@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:20:32 +0800 Subject: [PATCH 3/3] fix(regex): add regex for left angle operator sequences in cpplint.py --- cpplint.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cpplint.py b/cpplint.py index 376a355..2b259e4 100755 --- a/cpplint.py +++ b/cpplint.py @@ -920,6 +920,10 @@ # Match string that indicates we're working on a Linux Kernel file. _SEARCH_KERNEL_FILE = re.compile(r"\b(?:LINT_KERNEL_FILE)") +# Operator sequences beginning with '<' (used to strip before counting angle brackets). +# Longer sequences must come first so '<<=' is not partially matched as '<<'. +_LANGLE_OPS_RE = re.compile(r"<<=|<=|<<") + # Commands for sed to fix the problem _SED_FIXUPS = { "Remove spaces around =": r"s/ = /=/", @@ -3981,7 +3985,6 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, # characters do not trigger the joining loop (condition is # count('<') > count('>')), and stripping '>>' would break nested # template types such as vector>. - _LANGLE_OPS_RE = re.compile(r"<<=|<=|<<") i = 0 while i < len(constructor_args): constructor_arg = constructor_args[i]