Skip to content

String literals count as evidence in 16 gates — and 8 of them are ONE hole in source_scope.markup_mask #424

Description

@rubenvdlinde

Found by the all-65 survey of the #415/#420 comment class. Full table: fleet-board/findings/gates-comment-class.md. Companions: #422 (false-negative half), #423 (false-positive half), #421 (gate-45).

This is the adjacent variant the survey was asked to flag: evidence inside a string literal counts. It splits into two groups, and the second one is the reason this is a single issue rather than sixteen.


Group 1 — blank_strings=False, or no string awareness at all

These are checkers whose comment axis was separately verified clean. Only the literal gets through.

gate site fixture
8 unsafe-auth-resolver php_mask(src) L101, default blank_strings=False $doc = 'catch (\Throwable $e) { return null; }'; in a correctly-rethrowing resolver → FAIL — 1 fail-open pattern(s)
10 initial-state js_comment_mask keeps strings const doc = "document.getElementById('fx-settings').dataset.version"FAIL — 1 DOM read(s)
11 admin-router same the routes.push({path:'/settings', component: AdminRoot}) text as a double-quoted constant → FAIL — 1 admin route/import
13 modal-isolation runner inline PYMI masks comments, never literals const help = 'use <NcDialog> for confirmations'FAIL — 1 file(s) with inline modal/dialog
18 notification-dialect tokens matched against json.dumps(rule) a description warning against the legacy dialect → FAIL — 1 legacy-dialect token(s)
53 effective-manifest-crossref stripJsComments() L247 applied but not string-aware glob: '/*.vue' on a registry entry → FAIL — 1 cross-reference failure
59 unclosable-gate php_mask L174 IS used (its suite mutation-checks it) but blank_strings=False $hint = "call setValueString('fixapp','configuration_version','3') next"; → PASS (false negative — a string closes the gate)
64 apphost-autoload-prelude strip_comments() L207 is a proper state machine and IS applied; it preserves literals $hint = "we call \OC_App::registerAutoloading('openregister', $p) before this"; → PASS (false negative)

⚠️ blank_strings is a per-caller decision and both settings are right somewhere. gate-34 and gate-58 look for string literals (window['confirm'], 'networkidle') and blanking contents would turn a fixed gate into a dead one. gate-48's 'OCS-APIRequest': 'true' is a header name that IS a string. So this is not a flag to flip globally — it is eight separate judgements, each needing a paired arm showing the real evidence survives.


Group 2 — the delimiter hole, which is ONE bug in the SHARED library 🔴

source_scope.markup_mask treats <!-- as opening a comment wherever it appears, including inside a string or a Vue interpolation. Measured directly:

markup_mask("<p>{{ '<!--' }}</p>\n<img alt=\"\" src=\"/a/avatarUrl.png\">\n<p>{{ '-->' }}</p>")
  → "<p>{{ '            \n                                   \n          ' }}</p>"

The <img alt=""> between them is blanked, and the gate goes green over live markup.

That single property makes gates 35 and 36 affected today. And six more checkers each carry their own private copy of COMMENT = re.compile(r'<!--.*?-->', re.DOTALL) with the same hole — 37, 39, 40, 42, 43, 44 — plus php_template_scope.py for 41.

🔑 This is why the obvious consolidation is currently the wrong move. Routing those eight into markup_mask — the library extracted in #184/#249 precisely to stop this drift — would fix their comment half and leave this half armed, while making it look like the class had been closed at one site.

Order of operations

  1. Harden source_scope.markup_mask so <!-- inside a quoted attribute value or a {{ }} interpolation is not a comment opener, with a mutation-checked arm (flip the branch, the arm goes red).
  2. Prove gates 35 and 36 flip on the fixture above.
  3. Then migrate the six private copies + php_template_scope, one site, with each gate's existing suite as the regression.

⚠️ A mask that over-blanks is a gate that reports nothing — which is the failure mode this whole programme exists to remove. source_scope's own header already records one instance (<template> nests, and a lazy quantifier silently dropped a real unlabelled <NcSelect> at openconnector EditMapping.vue:376). Same trap, same file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions