Re: [rfc] str_mask function
| From: | Weilin Du | Date: | Sat, 19 Sep 2026 06:09:54 +0000 |
| Subject: | Re: [rfc] str_mask function | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-132550@lists.php.net to get a copy of this message | ||
Hi,
> 1. Ergonomics & Clarity: Masking sensitive information (PII, credit cards, emails,
tokens) is one of the most common everyday tasks in modern web security and logging. Writing
substr_replace(..., str_repeat(...), ...) is verbose and prone to off-by-one errors. A
dedicated function makes the intent clear.
I don't think it is verbose. Perhaps different people have different coding styles. But I down
vote on that statement.
> 2. Fail-Closed Security & Strict Validation: Data masking often deals with
sensitive credentials. substr_replace() has legacy and lenient behaviors regarding
out-of-bounds offsets. In contrast, str_mask() is designed with a strict fail-closed
approach (throwing ValueError on invalid boundaries or empty mask characters) to ensure
sensitive data is never silently exposed due to silent clipping.
Can you provide an actual example of out-of-bounds offsets and it's impact for us to
understand?
> 3. Performance & Memory: The substr_replace + str_repeat combination
performs two separate string allocations (one temporary string created by str_repeat
and the final string created by substr_replace). str_mask() computes the
masked string directly in C in a single allocation pass, making it more memory- and CPU-efficient.
Well, I'd argue that the str_repeat here is basically for better readability. That
$phone_number = '+989123456789';
$masked_phone = substr_replace($phone_number, str_repeat('X', 4), -4);
Can be written to
$phone_number = '+989123456789';
$masked_phone = substr_replace($phone_number, 'XXXX', -4);
So there is only one single allocation. The second one you are pointing to comes from repeating the
string, which is not what we are arguing about here.
Cheers,
Weilin Du