> 5; $i = $b & 0x1f; $n = self::uint( $d, $o, $i ); switch ( $t ) { case 0: return $n; case 1: return -1 - $n; case 2: $s = substr( $d, $o, $n ); $o += $n; return $s; case 3: $s = substr( $d, $o, $n ); $o += $n; return $s; case 4: // $n comes straight from attacker-controlled input and can claim up to // ~1.8e19 elements; bound it against the remaining buffer size (each // element needs at least 1 byte) so malformed/hostile CBOR fails fast // instead of looping until the request times out or exhausts memory. if ( $n > strlen( $d ) - $o ) { throw new \RuntimeException( 'CBOR: array length exceeds remaining buffer' ); } $a = array(); for ( $j = 0; $j < $n; $j++ ) { $a[] = self::item( $d, $o ); } return $a; case 5: // Same bound as case 4, a map entry needs at least 2 bytes (key + value) // but this looser 1-byte-per-count check is still sufficient to cap the // loop at O(strlen($d)) instead of an attacker-chosen 64-bit count. if ( $n > strlen( $d ) - $o ) { throw new \RuntimeException( 'CBOR: map length exceeds remaining buffer' ); } $m = array(); for ( $j = 0; $j < $n; $j++ ) { $k = self::item( $d, $o ); $m[ $k ] = self::item( $d, $o ); } return $m; case 6: return self::item( $d, $o ); case 7: if ( $i === 20 ) { return false; } if ( $i === 21 ) { return true; } if ( $i === 22 || $i === 23 ) { return null; } if ( $i === 25 ) { $o += 2; return 0.0; } if ( $i === 26 ) { $f = unpack( 'G', substr( $d, $o, 4 ) )[1]; $o += 4; return $f; } if ( $i === 27 ) { $f = unpack( 'E', substr( $d, $o, 8 ) )[1]; $o += 8; return $f; } } return null; } private static function uint( string $d, int &$o, int $i ): int { if ( $i <= 23 ) { return $i; } if ( $i === 24 ) { return ord( $d[ $o++ ] ); } if ( $i === 25 ) { $v = unpack( 'n', substr( $d, $o, 2 ) )[1]; $o += 2; return $v; } if ( $i === 26 ) { $v = unpack( 'N', substr( $d, $o, 4 ) )[1]; $o += 4; return $v; } if ( $i === 27 ) { $hi = unpack( 'N', substr( $d, $o, 4 ) )[1]; $lo = unpack( 'N', substr( $d, $o + 4, 4 ) )[1]; $o += 8; return $hi * 4294967296 + $lo; } throw new \RuntimeException( esc_html( "CBOR: unsupported additional info $i" ) ); } }