@@ -308,11 +308,21 @@ PHP_LIBXML_API zend_string *php_libxml_sniff_charset_from_stream(const php_strea
308308 if (Z_TYPE (s -> wrapperdata ) == IS_ARRAY ) {
309309 zval * header ;
310310
311- ZEND_HASH_FOREACH_VAL_IND (Z_ARRVAL (s -> wrapperdata ), header ) {
312- const char buf [] = "Content-Type:" ;
313- if (Z_TYPE_P (header ) == IS_STRING &&
314- !zend_binary_strncasecmp (Z_STRVAL_P (header ), Z_STRLEN_P (header ), buf , sizeof (buf )- 1 , sizeof (buf )- 1 )) {
315- return php_libxml_sniff_charset_from_string (Z_STRVAL_P (header ) + sizeof (buf ) - 1 , Z_STRVAL_P (header ) + Z_STRLEN_P (header ));
311+ /* Scan backwards: The header array might contain the headers for multiple responses, if
312+ * a redirect was followed.
313+ */
314+ ZEND_HASH_REVERSE_FOREACH_VAL_IND (Z_ARRVAL (s -> wrapperdata ), header ) {
315+ if (Z_TYPE_P (header ) == IS_STRING ) {
316+ /* If no colon is found in the header, we assume it's the HTTP status line and bail out. */
317+ char * colon = memchr (Z_STRVAL_P (header ), ':' , Z_STRLEN_P (header ));
318+ char * space = memchr (Z_STRVAL_P (header ), ' ' , Z_STRLEN_P (header ));
319+ if (colon == NULL || space < colon ) {
320+ return NULL ;
321+ }
322+
323+ if (zend_string_starts_with_literal_ci (Z_STR_P (header ), "content-type:" )) {
324+ return php_libxml_sniff_charset_from_string (Z_STRVAL_P (header ) + strlen ("content-type:" ), Z_STRVAL_P (header ) + Z_STRLEN_P (header ));
325+ }
316326 }
317327 } ZEND_HASH_FOREACH_END ();
318328 }
0 commit comments