diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc index 4c9d2a754bff..add8c3ae70ac 100644 --- a/ext/ftp/tests/server.inc +++ b/ext/ftp/tests/server.inc @@ -290,7 +290,7 @@ if ($pid) { } if (empty($m[1]) || $m[1] !== 'emptydir') { - fputs($fs, "file1\r\nfile1\r\nfile\nb0rk\r\n"); + fputs($fs, $nlst_data ?? "file1\r\nfile1\r\nfile\nb0rk\r\n"); } fputs($s, "226 Closing data Connection.\r\n"); diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 16617078d3c1..8b78308f9426 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -2217,9 +2217,9 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool /* Force UID and PWD to be set in the DSN */ if (use_uid_arg || use_pwd_arg) { - db_end--; - if ((unsigned char)*(db_end) == ';') { - *db_end = '\0'; + size_t base_len = db_len; + if (base_len > 0 && db[base_len - 1] == ';') { + base_len--; } char *uid_quoted = NULL, *pwd_quoted = NULL; @@ -2235,7 +2235,7 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool } if (!use_pwd_arg) { - spprintf(&ldb, 0, "%s;UID=%s;", db, uid_quoted); + spprintf(&ldb, 0, "%.*s;UID=%s;", (int) base_len, db, uid_quoted); } } @@ -2250,12 +2250,12 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool } if (!use_uid_arg) { - spprintf(&ldb, 0, "%s;PWD=%s;", db, pwd_quoted); + spprintf(&ldb, 0, "%.*s;PWD=%s;", (int) base_len, db, pwd_quoted); } } if (use_uid_arg && use_pwd_arg) { - spprintf(&ldb, 0, "%s;UID=%s;PWD=%s;", db, uid_quoted, pwd_quoted); + spprintf(&ldb, 0, "%.*s;UID=%s;PWD=%s;", (int) base_len, db, uid_quoted, pwd_quoted); } if (uid_quoted && should_quote_uid) { diff --git a/ext/odbc/tests/gh_odbc_dsn_immutability.phpt b/ext/odbc/tests/gh_odbc_dsn_immutability.phpt new file mode 100644 index 000000000000..e3023b387c70 --- /dev/null +++ b/ext/odbc/tests/gh_odbc_dsn_immutability.phpt @@ -0,0 +1,20 @@ +--TEST-- +odbc_connect() must not mutate the caller's DSN string +--EXTENSIONS-- +odbc +--FILE-- + +--EXPECT-- +string(37) "Driver=DoesNotExist;Database=x;SS001;" +string(43) "Driver=DoesNotExist;Database=x;SS001_CONST;" diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index e9fd68007d26..125c92582008 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -956,14 +956,14 @@ int make_http_soap_request(zval *this_ptr, if (tmp != NULL) { tmp++; http_status = atoi(tmp); - } - tmp = strstr(tmp," "); - if (tmp != NULL) { - tmp++; - if (http_msg) { - efree(http_msg); + tmp = strstr(tmp," "); + if (tmp != NULL) { + tmp++; + if (http_msg) { + efree(http_msg); + } + http_msg = estrdup(tmp); } - http_msg = estrdup(tmp); } efree(http_version); diff --git a/ext/soap/tests/http_status_line_no_code.phpt b/ext/soap/tests/http_status_line_no_code.phpt new file mode 100644 index 000000000000..de943571a492 --- /dev/null +++ b/ext/soap/tests/http_status_line_no_code.phpt @@ -0,0 +1,33 @@ +--TEST-- +SoapClient: malformed HTTP status line without status code must not crash +--EXTENSIONS-- +soap +--FILE-- + 'http://{{ ADDR }}', + 'uri' => 'http://testuri.org', + 'connection_timeout' => 3, +]); +var_dump($client->__doRequest('', 'http://{{ ADDR }}', 'T', 1)); +CODE; + +include sprintf('%s/../../openssl/tests/ServerClientTestCase.inc', __DIR__); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--EXPECT-- +string(0) "" diff --git a/ext/standard/filters.c b/ext/standard/filters.c index a7c0a035a239..0c08600648cd 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -1715,12 +1715,14 @@ static size_t php_dechunk(char *buf, size_t len, php_chunked_filter_data *data) data->chunk_size = 0; case CHUNK_SIZE: while (p < end) { + size_t digit; + if (*p >= '0' && *p <= '9') { - data->chunk_size = (data->chunk_size * 16) + (*p - '0'); + digit = *p - '0'; } else if (*p >= 'A' && *p <= 'F') { - data->chunk_size = (data->chunk_size * 16) + (*p - 'A' + 10); + digit = *p - 'A' + 10; } else if (*p >= 'a' && *p <= 'f') { - data->chunk_size = (data->chunk_size * 16) + (*p - 'a' + 10); + digit = *p - 'a' + 10; } else if (data->state == CHUNK_SIZE_START) { data->state = CHUNK_ERROR; break; @@ -1728,6 +1730,11 @@ static size_t php_dechunk(char *buf, size_t len, php_chunked_filter_data *data) data->state = CHUNK_SIZE_EXT; break; } + if (data->chunk_size > (SIZE_MAX / 16)) { + data->state = CHUNK_ERROR; + break; + } + data->chunk_size = (data->chunk_size * 16) + digit; data->state = CHUNK_SIZE; p++; } diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 7b18e17f0d8f..fd7ecec02f19 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -625,9 +625,9 @@ static ssize_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t coun basename = php_basename(ent->d_name, tmp_len, NULL, 0); - tmp_len = MIN(sizeof(ent->d_name), ZSTR_LEN(basename) - 1); + tmp_len = MIN(sizeof(ent->d_name) - 1, ZSTR_LEN(basename)); memcpy(ent->d_name, ZSTR_VAL(basename), tmp_len); - ent->d_name[tmp_len - 1] = '\0'; + ent->d_name[tmp_len] = '\0'; zend_string_release_ex(basename, 0); ent->d_type = DT_UNKNOWN; diff --git a/ext/standard/tests/filters/dechunk_size_overflow.phpt b/ext/standard/tests/filters/dechunk_size_overflow.phpt new file mode 100644 index 000000000000..ac42733e16e0 --- /dev/null +++ b/ext/standard/tests/filters/dechunk_size_overflow.phpt @@ -0,0 +1,38 @@ +--TEST-- +dechunk filter must reject a chunk size that overflows size_t +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + +--EXPECTF-- +string(%d) "%s +BODYDATA +0 +" +string(%d) "%s +BODYDATA +0 +" +string(5) "hello" diff --git a/ext/standard/tests/streams/ftp_dirstream_oob.phpt b/ext/standard/tests/streams/ftp_dirstream_oob.phpt new file mode 100644 index 000000000000..9e184f3c8ac6 --- /dev/null +++ b/ext/standard/tests/streams/ftp_dirstream_oob.phpt @@ -0,0 +1,33 @@ +--TEST-- +opendir() with 'ftp://' stream must not go out of bounds on an empty or slash-only listing line +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +resource(%d) of type (stream) +string(5) "file1" +string(0) "" +string(4) "b0rk" +string(0) "" diff --git a/ext/standard/tests/streams/opendir-002.phpt b/ext/standard/tests/streams/opendir-002.phpt index 4978c8affa3d..0a5712564e2e 100644 --- a/ext/standard/tests/streams/opendir-002.phpt +++ b/ext/standard/tests/streams/opendir-002.phpt @@ -25,5 +25,5 @@ closedir($ds); resource(%d) of type (stream) string(5) "file1" string(5) "file1" -string(3) "fil" +string(4) "file" string(4) "b0rk" diff --git a/ext/standard/tests/streams/opendir-004.phpt b/ext/standard/tests/streams/opendir-004.phpt index 9ccb86b4f4b4..3f076e0d8386 100644 --- a/ext/standard/tests/streams/opendir-004.phpt +++ b/ext/standard/tests/streams/opendir-004.phpt @@ -27,5 +27,5 @@ while ($fn=readdir($ds)) { resource(%d) of type (stream) string(5) "file1" string(5) "file1" -string(3) "fil" +string(4) "file" string(4) "b0rk"