wppaste
WordPress

ParagonIE_Sodium_Core_Util::strlen( string $str ): int

Source
wp-includes/sodium_compat/src/Core/Util.php:786

Calculates the byte length of a string, bypassing mbstring overloading so sodium_compat always counts bytes not characters. It is an internal helper of the bundled sodium_compat polyfill used throughout WordPress's AEAD encryption and authentication routines, not a public API most plugins should call directly. Passing anything other than a string throws a native TypeError, and pairing it with ParagonIE_Sodium_Core_Util::substr() is how the library slices ciphertext safely byte by byte.

Safe string length

Compatibility

WordPress
core
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$strstring

Return value

int

Code examples

Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.

Compare byte length vs character length for a UTF-8 string

Run both a plain ASCII string and a string with accented characters through the sodium helper and mb_strlen() side by side.

$ascii = 'Hello world!';
$utf8  = 'Héllo wörld!';

printf(
    'ASCII: %s -> %d bytes (safe strlen) vs %d chars (mb_strlen)<br>',
    esc_html( $ascii ),
    ParagonIE_Sodium_Core_Util::strlen( $ascii ),
    mb_strlen( $ascii )
);

printf(
    'UTF-8: %s -> %d bytes (safe strlen) vs %d chars (mb_strlen)',
    esc_html( $utf8 ),
    ParagonIE_Sodium_Core_Util::strlen( $utf8 ),
    mb_strlen( $utf8 )
);

The accented characters take two bytes each in UTF-8, so the safe byte count is higher than the mb_strlen character count.

See what happens when a non-string value is passed in

Loop over a mix of a real string, an integer and null to trigger the method's own type check.

$values = array( 'a valid string', 42, null );

foreach ( $values as $value ) {
    try {
        $length = ParagonIE_Sodium_Core_Util::strlen( $value );
        printf( 'Value of type %s has length %d bytes<br>', esc_html( gettype( $value ) ), $length );
    } catch ( TypeError $e ) {
        printf( 'Rejected %s: %s<br>', esc_html( gettype( $value ) ), esc_html( $e->getMessage() ) );
    }
}

The TypeError comes straight from the method's own is_string() guard, not from PHP's native strict typing.

Common problems and fixes · 3

Why do I get a TypeError when calling this method?

The method runs its own is_string() check before doing anything else and throws a TypeError with the message "String expected" for anything that isn't a string, including integers, null and objects.

Why does my byte count not match mb_strlen()?

That's expected. This method deliberately counts bytes, not characters, because cryptographic routines in sodium_compat need exact byte lengths for keys, nonces and ciphertext. mb_strlen() counts characters under the current encoding, which is wrong for that job.

Does server configuration change what this returns?

Yes, in theory. The source checks isMbStringOverride() and, only when the legacy mbstring.func_overload ini setting has overridden PHP's native strlen(), falls back to mb_strlen($str, '8bit') to force byte counting instead of the overridden character count.

Alternatives and related functions

strlen
When you just need a byte count in ordinary PHP code and don't need the extra TypeError guard this method adds.
mb_strlen
When you're counting displayable characters in a multibyte string rather than raw bytes, such as for a character-limit UI.
ParagonIE_Sodium_Core_Util::substr
When you already know the byte length and now need to slice that same string safely by byte offset.

Performance profile

How much work a call to ParagonIE_Sodium_Core_Util::strlen() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Trivial

Touches nothing outside its own arguments.

Scaling
Constant

No loop in the body: the same number of instructions runs whatever you pass in.

Instructions
7–13

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 18.

Plugin surface
None

Nothing here hands control to plugin code.

Called by
50

50 places in core call this, so the cost is paid more often than your own code shows.

What one call costs · 3 distinct outcomes

One number would be a lie: the work depends on which branch runs. These are every distinct cost ParagonIE_Sodium_Core_Util::strlen() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
!is_string($str)7none
is_string($str) && !::isMbStringOverride()9::isMbStringOverride()
is_string($str) && ::isMbStringOverride()13::isMbStringOverride(), mb_strlen()

Across PHP versions

PHPCompiledExecutedBranchesNotes
8.6-dev187–132
8.5187–132
8.4187–132
8.3187–132
8.2187–132
8.1187–1322 fewer instructions than PHP 7.4
7.4207–142

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Uses · 3

Used by · 50

Show all 50

Source code

    public static function strlen($str)    {        /* Type checks: */        if (!is_string($str)) {            throw new TypeError('String expected');        }         return (int) (        self::isMbStringOverride()            ? mb_strlen($str, '8bit')            : strlen($str)        );    }

Changelog

Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

About this page

Parsed data
Generated from the wordpress-develop 7.1.0 tag, from src/wp-includes/sodium_compat/src/Core/Util.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.