Re: [rfc] str_mask function

From: Date: Fri, 18 Sep 2026 20:51:21 +0000
Subject: Re: [rfc] str_mask function
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-132545@lists.php.net to get a copy of this message
در تاریخ جمعه ۱۸ سپتامبر ۲۰۲۶، ۲۳:۱۲ Osama Aldemeery <aldemeery@gmail.com> نوشت: > ‪On Fri, Sep 18, 2026 at 9:27 PM ‫سپهر محمودی‬‎ > <sepehrphpr@gmail.com> > wrote:‬ > > > > Hi everyone, > > > > I'm officially starting my work on the ext/intl and standard string > functions, and I'm very excited to share my first major proposal for PHP > 8.7! > > > > I have successfully set up my local development environment and compiler > on my machine, and everything is up and running smoothly. > > > > As part of this, I would like to propose a new native function called > str_mask(). > > > > ### Proposal Overview > > The str_mask() function is designed to securely mask portions of a > string using a specified mask character. This is extremely useful for > handling sensitive user data like credit card numbers, phone numbers, and > tokens. > > > > Signature: > > str_mask(string $string, string $mask_char = '*', int $offset = 0, ?int > $length = null): string > > > > ### Examples > > 1. Masking a credit card (positive offset & length): > > $credit_card = '1234567890123456'; > > $masked_card = str_mask($credit_card, '*', 4, 8); > > // Output: 1234********3456 > > > > 2. Masking a phone number (negative offset to count from the end): > > $phone_number = '+989123456789'; > > $masked_phone = str_mask($phone_number, 'X', -4); > > // Output: +9891234XXXX > > > > You can find all the details, implementation plans, and RFC discussions > here: > > https://wiki.php.net/rfc/str_mask > > > > Looking forward to hearing your feedback and thoughts! > > > > Best regards, > > Sepehr Mahmoudi > > Hi, > > Unless I am missing something...this looks identical to the existing > substr_replace. It has the same signature with just a different > name > and without array being part of the params/return types. > > Your examples could be rewritten as: > > ``` > $credit_card = '1234567890123456'; > $masked_card = substr_replace($credit_card, str_repeat('*', 8), 4, 8); > > $phone_number = '+989123456789'; > $masked_phone = substr_replace($phone_number, str_repeat('X', 4), -4); > ``` > > Regards, > Osama > -------- Hi Osama, Thank you for the feedback! While it is true that masking can be composed using `substr_replace($str, str_repeat($mask, $len), $offset, $len)`, there are three key motivations behind proposing str_mask(): 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. 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. 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. Best regards, Sepehr

« previous php.internals (#132545) next »