Notes › Tech Notes › Star Run Length Is Hardcoded: the Masking Page Cuts a Fixed 4, 3, 11 or 12 Stars, an 18-Unit String Is Taken by the Phone Tier, an Empty Box Falls Back to *

Star Run Length Is Hardcoded: the Masking Page Cuts a Fixed 4, 3, 11 or 12 Stars, an 18-Unit String Is Taken by the Phone Tier, an Empty Box Falls Back to *

Star counts across the five mask patterns are hardcoded: 4, 3, 11, 12 and 2 stars that ignore input length, an 18-unit string taken first by the unanchored phone tier, an idle id-card tier, an unreachable overlap window, plus the empty-box fallback and the stats column.

One text mixes several kinds of numbers: what each tier does once you tick it

The trigger is concrete: the pasted text held strings of 11, 18 and 16 code units, all five tick boxes were lit, and each tier swallowed its own share of cells. How it was run: the template is 7386 bytes / 152 lines, the script block ran as-is at 2853 code units, and the five regular expressions, repeat and doMask were neither rewritten nor patched; the DOM was only a stub addressed by id, pure Node. Every figure is measured at the string layer and every length counts UTF-16 code units. Each sample string is either a fictional input stitched from sequential and repeated digits, or the default sample the template ships with, so nothing here belongs to a real number: this article only does string arithmetic.

The page under test is Privacy Masking: its default input is the 4-line / 108-code-unit sample baked into the template, and loading runs doMask once (L150) with no button.

The star count is a hardcoded constant, not a function of input length

In all five replacement patterns the upper bound handed to repeat is a literal: six call sites, with constants 4, 3, 11, 4, 4 and 4 (L98 / L106 / L114 / L124), while the IP tier (L132) skips repeat and appends 2 stars directly.

TierStar countReplacement shapeShare left exposed
phone43 head + 4 stars + 4 tail63.6%
email3first character + 3 stars25.0%
id card113 head + 11 stars + 4 tail38.9%
card12three groups of 4 stars plus spaces21.1%
IP2keep the first two groups and rebuild54.5%

Nothing changes that constant as the input grows or shrinks: the card tier was fed 16, 17, 18 and 19 code units, and the stars stayed 12, the output stayed 19 code units and the exposed digits stayed 4; the phone tier ran from 11 code units up to 30 and the stars stayed 4, with one hit each time; the id-card tier only hits at 18 code units, where the stars stay 11. Being longer than the template is not a downgrade but no handling at all: a pure digit string of 20..40 code units scores 0 hits with five tiers ticked and leaves 100.0% exposed.

repeat constants against input length phone 4 stars input 11 / 12 / 20 units stars stay 4 card 12 stars input 16 / 17 / 18 / 19 units output stays 19 id card 11 stars only the 18-unit case hits 1 hit email 3 stars, IP 2 stars IP off by default Segment length tracks neither input nor match.

Figure 1: the constant readings of the five tiers.

Input shorter than the template lands in neither the mask nor the overlap

The overlap case: head takes 3 and tail takes 4, so a hit shorter than 3+4 = 7 code units makes the two slices share one cell and exposes the plaintext twice (the hypothetical table gives 123****3456 at n=6, index 2 twice). But the three patterns that call slice never reach a hit that short: the phone pattern spends a fixed 11 units on 1 literal, 1 character class and 9 more, the id-card pattern 17+1 = 18, and the card pattern covers 16..19, so the minimum hit lengths 11, 18 and 16 sit 4, 11 and 9 units above the threshold of 7; a bare run over 400 targeted corpus rows reports 0 hits under 7 in all five tiers. The other two tiers never slice, so overlap exposure is unreachable here.

Exposure comes from the missing anchor: an 18-unit string is taken by the phone tier

Three patterns carry \b (id card, card and IP) while phone and email do not, and the difference shows on line 2: the measured output is 身份证号:110101199****11234, which keeps 4 stars and leaves 14 digit code units in the clear, 77.8% of the 18 units. The phone tier has no boundary anchor, so it hits once inside the 18-unit id-card string first and rewrites the input the id-card tier was about to read; only with the phone tier switched off alone do you get 110***********1234, with 11 stars and 7 digits exposed. The stats column prints 4, 2, 1, 1 with no id-card row at all, because that tier idles on its own first screen: turning idcard off moves nothing against the all-ticked output, the first differing position is -1, and the 32 tick combinations collapse into 24 distinct strings; all 8 redundant groups come from this tier.

The five replace calls run in a fixed order and the leftover decides who takes over

The chain is phone, email, id card, card, IP, so the output of one pattern is the input of the next. Once the phone tier finishes slicing, its trailing 4 units sit against the digits behind them, and the card tier takes over only if 4 plus the leftover falls inside 16..19. An input of 24 code units, 138123456781234567890123, is cut by the phone tier first, then the card tier hits a leftover of length 17 and prints 16 stars; lengthened to 27 units the leftover becomes 20, above 19, so the card tier scores 0 hits. The email tier works the same way: a local part that swallows a digit run of 11 units (31 units for the line) is cut open by the phone tier first, and email then works on what remains, ending at 7 stars, 15 units away from ticking email alone.

The consumption order of the five replace calls phone → email → id card → card → IP 24 units phone cuts first, card hits the leftover length 17, 16 stars 27 units leftover 20 exceeds 19 card tier, 0 hits 31 units email takes over on the leftover 7 stars Handoff window: 4 plus the leftover lands in 16..19.

Figure 2: the chaining order and the handoff window.

Three readings of the mask-character box

The box is written as value="*" with maxlength="1" (L35), and the reading sentence (L84) only falls back when the value is an empty string. Clear the box and 13812345678 still yields 138****5678, 4 stars, character for character the default output. Type a single space instead: a space is truthy so no fallback happens, and the result keeps 4 space units inside its 11 with 0 stars. Forcing two characters through the stub makes repeat emit 8 units and the phone tier output 15 units. Whether two typed characters are truncated to one cell, and whether the preset buttons obey the same limit, belongs to the browser control layer; this batch ran pure Node without headless Chrome, so both stay untested.

The stats column counts hits, not rows

The five counters increment only inside their own replace callback, and the total is the sum of the five (L139); a tier with 0 hits renders no row. Three phone numbers on 1 line count as 3 hits and 12 stars while the output is still 1 line; 100 rows of the repeated sample report 200 hits although the row count is only 100; an empty input returns early and the stats column is written as 0 code units rather than 0 hits. Paste the result back and mask it again: round 1 takes the sample from 108 down to 104 code units, round 2 returns output identical to its input with 23 stars still standing.

The IP tier is unticked by default yet the copy lists it with the other four

Reading the attributes literally: the first four inputs carry checked (L18 / L21 / L24 / L27) and mask-ip (L30) does not, so on the default first screen line 4 equals its input exactly, with 0 stars. Tick it and a 13-unit value becomes 11 units with 2 more stars, and the star ledger grows from 23 to 25. Of the 16 copy items 15 can be settled: 8 agree, 5 agree partly, 2 conflict. One conflict is the whole-page claim about masking the middle 11 digits, since the id-card tier scores 0 hits on the first screen, off by 7 stars; the other writes the unticked IP tier as automatic detection.

Two pages keep two different rulers for what counts as a hit

This page only replaces, it never selects: its criterion is how many times the five patterns hit. Pulling fields out by type is the job of Text Extractor, and the two pages do not measure with the same ruler. The ceiling the built-in types run into on the extraction side was measured in an older on-site article, whose numbers are not repeated here.

Frequently asked questions

Q: Does the star count move when the input length changes?

No. Card inputs from 16 to 19 code units keep 12 stars and an output of 19 units; phone inputs from 11 to 30 units keep 4 stars.

Q: Does a string under 7 code units repeat the plaintext?

Arithmetically it would, because at n=6 the head and the tail share the digit at index 2, but the three slicing patterns have minimum hit lengths of 11, 18 and 16 and never reach the threshold, so the overlap stays unreachable here.

Q: I ticked the id-card tier, so why is there no id-card row in the stats?

The 18-unit string is rewritten by the earlier phone tier, so the id-card tier receives a middle string that already carries mask characters, and a tier with 0 hits renders no row.

📎 Related articles

The Lock Is One-Way and Percent Is Two Rulers: pct 50 Gives 619x430, and All Four PNG Quality Stops Return 6971 B 2026-11-13 A Month on This Page Is Hard-Coded as 30 Days: the Six Fixed Divisors, 13-Digit Millisecond Input, and slice(0,16) Truncation Measured Under UTC+8 and UTC-5 2026-11-13 Both Tabs Recompute the Same C(n,r): n=20 Writes Out 40 Factors, n=21 Writes None, a 300-Digit Result and Two Readings of r=0 2026-11-13 Eight elements compute 40320 permutations but list only 5000 rows: two unrelated caps on the permutation page, duplicates counted by 3!, and the process break at n above 20 2026-11-12 Assembly Order and Case Folding for Ad Links: Six UTM States, Two Hard Caps and Five Panel Fields on Their Own Scales 2026-11-12