From a6ad8dc30239dd31e6008197117038051d139104 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 20:40:00 -0400 Subject: [PATCH 1/8] memory audit fixes --- oauth.c | 24 ++++++++++++++++++------ provider.c | 9 ++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/oauth.c b/oauth.c index f1c1c35..af2acfd 100644 --- a/oauth.c +++ b/oauth.c @@ -158,10 +158,6 @@ static void so_object_free_storage(zend_object *obj) /* {{{ */ soo->debug_info = NULL; } - smart_string_free(&soo->headers_in); - if (soo->headers_out.c) { - smart_string_free(&soo->headers_out); - } if(Z_TYPE(soo->debugArr) != IS_UNDEF) { zval_ptr_dtor(&soo->debugArr); } @@ -172,6 +168,15 @@ static void so_object_free_storage(zend_object *obj) /* {{{ */ if (soo->timestamp) { efree(soo->timestamp); } + if (soo->multipart_files_num) { + int mi; + for (mi = 0; mi < soo->multipart_files_num; mi++) { + efree(soo->multipart_files[mi]); + efree(soo->multipart_params[mi]); + } + efree(soo->multipart_files); + efree(soo->multipart_params); + } } /* }}} */ @@ -482,8 +487,8 @@ int oauth_http_build_query(php_so_object *soo, smart_string *s, HashTable *args, soo->multipart_params = erealloc(soo->multipart_params, sizeof(char *) * (soo->multipart_files_num + 1)); convert_to_string_ex(cur_val); - soo->multipart_files[soo->multipart_files_num] = Z_STRVAL_P(cur_val); - soo->multipart_params[soo->multipart_files_num] = ZSTR_VAL(cur_key); + soo->multipart_files[soo->multipart_files_num] = estrdup(Z_STRVAL_P(cur_val)); + soo->multipart_params[soo->multipart_files_num] = estrdup(ZSTR_VAL(cur_key)); ++soo->multipart_files_num; /* we don't add multipart files to the params */ @@ -1714,8 +1719,15 @@ static long oauth_fetch(php_so_object *soo, const char *url, const char *method, case OAUTH_REQENGINE_CURL: http_response_code = make_req_curl(soo, surl.c, &payload, final_http_method, &rheaders); if (soo->multipart_files_num) { + int mi; + for (mi = 0; mi < soo->multipart_files_num; mi++) { + efree(soo->multipart_files[mi]); + efree(soo->multipart_params[mi]); + } efree(soo->multipart_files); efree(soo->multipart_params); + soo->multipart_files = NULL; + soo->multipart_params = NULL; soo->multipart_files_num = 0; soo->is_multipart = 0; } diff --git a/provider.c b/provider.c index da09647..757f965 100644 --- a/provider.c +++ b/provider.c @@ -271,11 +271,15 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ tmp = estrndup(Z_STRVAL_P(current_val), Z_STRLEN_P(current_val)); decoded_len = php_url_decode(tmp, Z_STRLEN_P(current_val)); ZVAL_STRINGL(&decoded_val, tmp, decoded_len); + efree(tmp); if (oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val)==FAILURE) { + zval_ptr_dtor(&decoded_val); + zval_ptr_dtor(&return_value); + zval_ptr_dtor(&subpats); return FAILURE; } - Z_DELREF(decoded_val); + zval_ptr_dtor(&decoded_val); } } while (SUCCESS==zend_hash_move_forward_ex(Z_ARRVAL(subpats), &hpos)); @@ -318,6 +322,9 @@ static void oauth_provider_register_cb(INTERNAL_FUNCTION_PARAMETERS, int type) / tgt_cb = &sop->tsnonce_handler; break; default: + zval_ptr_dtor(&cb->fcall_info->function_name); + efree(cb->fcall_info); + efree(cb); php_error_docref(NULL, E_ERROR, "Invalid callback type for OAuthProvider"); return; } From 32a0c7e22ebf935be772208cc61a52fc602be8f1 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 20:52:08 -0400 Subject: [PATCH 2/8] memory audit fixes --- oauth.c | 30 ++++++++++++++++-------------- provider.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/oauth.c b/oauth.c index af2acfd..7b0aa98 100644 --- a/oauth.c +++ b/oauth.c @@ -1132,15 +1132,16 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl } for(i=0; i < soo->multipart_files_num; i++) { - char *type = NULL, *filename = NULL, *postval, *postval_orig; + char *type = NULL, *filename = NULL, *postval, *postval_orig, *param_name; curl_mimepart *part; /* swiped from ext/curl/interface.c to help with consistency */ postval_orig = postval = estrdup(soo->multipart_files[i]); + param_name = soo->multipart_params[i]; - if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { + if (postval[0] == '@' && param_name[0] == '@') { /* :< (chomp) @ */ - ++soo->multipart_params[i]; + ++param_name; ++postval; if((type = (char *) php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { @@ -1166,7 +1167,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl efree(postval_orig); goto cleanup; } - mres = curl_mime_name(part, soo->multipart_params[i]); + mres = curl_mime_name(part, param_name); if (mres == CURLE_OK) mres = curl_mime_filedata(part, postval); if (mres == CURLE_OK && filename) mres = curl_mime_filename(part, filename + sizeof(";filename=") - 1); if (mres == CURLE_OK) mres = curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); @@ -1185,7 +1186,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl efree(postval_orig); goto cleanup; } - mres = curl_mime_name(part, soo->multipart_params[i]); + mres = curl_mime_name(part, param_name); if (mres == CURLE_OK) mres = curl_mime_data(part, postval, CURL_ZERO_TERMINATED); if (mres != CURLE_OK) { char *em; @@ -1204,12 +1205,13 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl int i; for(i=0; i < soo->multipart_files_num; i++) { - char *type = NULL, *filename = NULL, *postval, *postval_orig; + char *type = NULL, *filename = NULL, *postval, *postval_orig, *param_name; postval_orig = postval = estrdup(soo->multipart_files[i]); + param_name = soo->multipart_params[i]; - if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { - ++soo->multipart_params[i]; + if (postval[0] == '@' && param_name[0] == '@') { + ++param_name; ++postval; if((type = (char *) php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { @@ -1230,24 +1232,24 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl if (filename) { curl_formadd(&ff, &lf, - CURLFORM_COPYNAME, soo->multipart_params[i], - CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), + CURLFORM_COPYNAME, param_name, + CURLFORM_NAMELENGTH, (long)strlen(param_name), CURLFORM_FILENAME, filename + sizeof(";filename=") - 1, CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", CURLFORM_FILE, postval, CURLFORM_END); } else { curl_formadd(&ff, &lf, - CURLFORM_COPYNAME, soo->multipart_params[i], - CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), + CURLFORM_COPYNAME, param_name, + CURLFORM_NAMELENGTH, (long)strlen(param_name), CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", CURLFORM_FILE, postval, CURLFORM_END); } } else { curl_formadd(&ff, &lf, - CURLFORM_COPYNAME, soo->multipart_params[i], - CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), + CURLFORM_COPYNAME, param_name, + CURLFORM_NAMELENGTH, (long)strlen(param_name), CURLFORM_COPYCONTENTS, postval, CURLFORM_CONTENTSLENGTH, (long)strlen(postval), CURLFORM_END); diff --git a/provider.c b/provider.c index 757f965..3f73aca 100644 --- a/provider.c +++ b/provider.c @@ -211,12 +211,19 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ size_t decoded_len; if(!auth_header || strncasecmp(auth_header, "oauth", 4) || !sop) { +#if PHP_VERSION_ID >= 70400 + zend_string_release(s_auth_header); +#endif + zend_string_release(regex); return FAILURE; } /* pass "OAuth " */ auth_header += 5; if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) { +#if PHP_VERSION_ID >= 70400 + zend_string_release(s_auth_header); +#endif zend_string_release(regex); return FAILURE; } @@ -246,6 +253,9 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ ); if (0 == Z_LVAL(return_value)) { +#if PHP_VERSION_ID >= 70400 + zend_string_release(s_auth_header); +#endif return FAILURE; } @@ -277,6 +287,9 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ zval_ptr_dtor(&decoded_val); zval_ptr_dtor(&return_value); zval_ptr_dtor(&subpats); +#if PHP_VERSION_ID >= 70400 + zend_string_release(s_auth_header); +#endif return FAILURE; } zval_ptr_dtor(&decoded_val); @@ -285,6 +298,9 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ zval_ptr_dtor(&return_value); zval_ptr_dtor(&subpats); +#if PHP_VERSION_ID >= 70400 + zend_string_release(s_auth_header); +#endif return SUCCESS; } From 53f721f4afc3e333d1a0c15bed243538e3d70a4f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 21:01:22 -0400 Subject: [PATCH 3/8] address reviews --- oauth.c | 27 ++++++++++++++------------- provider.c | 9 +++++---- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/oauth.c b/oauth.c index 7b0aa98..98b93ee 100644 --- a/oauth.c +++ b/oauth.c @@ -1720,23 +1720,24 @@ static long oauth_fetch(php_so_object *soo, const char *url, const char *method, #if OAUTH_USE_CURL case OAUTH_REQENGINE_CURL: http_response_code = make_req_curl(soo, surl.c, &payload, final_http_method, &rheaders); - if (soo->multipart_files_num) { - int mi; - for (mi = 0; mi < soo->multipart_files_num; mi++) { - efree(soo->multipart_files[mi]); - efree(soo->multipart_params[mi]); - } - efree(soo->multipart_files); - efree(soo->multipart_params); - soo->multipart_files = NULL; - soo->multipart_params = NULL; - soo->multipart_files_num = 0; - soo->is_multipart = 0; - } break; #endif } + if (soo->multipart_files_num) { + int mi; + for (mi = 0; mi < soo->multipart_files_num; mi++) { + efree(soo->multipart_files[mi]); + efree(soo->multipart_params[mi]); + } + efree(soo->multipart_files); + efree(soo->multipart_params); + soo->multipart_files = NULL; + soo->multipart_params = NULL; + soo->multipart_files_num = 0; + soo->is_multipart = 0; + } + is_redirect = HTTP_IS_REDIRECT(http_response_code); if(soo->debug) { diff --git a/provider.c b/provider.c index 3f73aca..56dffc7 100644 --- a/provider.c +++ b/provider.c @@ -206,20 +206,21 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ HashPosition hpos; zend_string *regex = zend_string_init(OAUTH_REGEX, sizeof(OAUTH_REGEX) - 1, 0); #if PHP_VERSION_ID >= 70400 - zend_string *s_auth_header = zend_string_init(auth_header, strlen(auth_header), 0); + zend_string *s_auth_header; #endif size_t decoded_len; if(!auth_header || strncasecmp(auth_header, "oauth", 4) || !sop) { -#if PHP_VERSION_ID >= 70400 - zend_string_release(s_auth_header); -#endif zend_string_release(regex); return FAILURE; } /* pass "OAuth " */ auth_header += 5; +#if PHP_VERSION_ID >= 70400 + s_auth_header = zend_string_init(auth_header, strlen(auth_header), 0); +#endif + if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) { #if PHP_VERSION_ID >= 70400 zend_string_release(s_auth_header); From 57a1f3f4afae4afbb5ba8f38c89faee24a854104 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 21:16:26 -0400 Subject: [PATCH 4/8] address reviews --- provider.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/provider.c b/provider.c index 56dffc7..0ef63b3 100644 --- a/provider.c +++ b/provider.c @@ -195,7 +195,7 @@ static void oauth_provider_set_std_params(zval *provider_obj, HashTable *sbs_var static inline int oauth_provider_set_param_value(HashTable *ht, char *key, zval *val) /* {{{ */ { Z_TRY_ADDREF_P(val); - return zend_hash_str_update(ht, key, strlen(key), val) != NULL; + return zend_hash_str_update(ht, key, strlen(key), val) != NULL ? SUCCESS : FAILURE; } /* }}} */ @@ -254,6 +254,8 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ ); if (0 == Z_LVAL(return_value)) { + zval_ptr_dtor(&return_value); + zval_ptr_dtor(&subpats); #if PHP_VERSION_ID >= 70400 zend_string_release(s_auth_header); #endif From b89153b3626ecfcafa0a71206dcbc556fedc45ae Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 21:32:09 -0400 Subject: [PATCH 5/8] address reviews --- provider.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/provider.c b/provider.c index 0ef63b3..654411d 100644 --- a/provider.c +++ b/provider.c @@ -195,7 +195,11 @@ static void oauth_provider_set_std_params(zval *provider_obj, HashTable *sbs_var static inline int oauth_provider_set_param_value(HashTable *ht, char *key, zval *val) /* {{{ */ { Z_TRY_ADDREF_P(val); - return zend_hash_str_update(ht, key, strlen(key), val) != NULL ? SUCCESS : FAILURE; + if (zend_hash_str_update(ht, key, strlen(key), val) == NULL) { + Z_TRY_DELREF_P(val); + return FAILURE; + } + return SUCCESS; } /* }}} */ From 729394d83cae8b9bc4f6e16cd32f243780683cec Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 21:43:53 -0400 Subject: [PATCH 6/8] address reviews --- oauth.c | 18 +++++++++++++----- provider.c | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/oauth.c b/oauth.c index 98b93ee..2771bc9 100644 --- a/oauth.c +++ b/oauth.c @@ -168,14 +168,22 @@ static void so_object_free_storage(zend_object *obj) /* {{{ */ if (soo->timestamp) { efree(soo->timestamp); } - if (soo->multipart_files_num) { + if (soo->multipart_files || soo->multipart_params) { int mi; for (mi = 0; mi < soo->multipart_files_num; mi++) { - efree(soo->multipart_files[mi]); - efree(soo->multipart_params[mi]); + if (soo->multipart_files) { + efree(soo->multipart_files[mi]); + } + if (soo->multipart_params) { + efree(soo->multipart_params[mi]); + } + } + if (soo->multipart_files) { + efree(soo->multipart_files); + } + if (soo->multipart_params) { + efree(soo->multipart_params); } - efree(soo->multipart_files); - efree(soo->multipart_params); } } diff --git a/provider.c b/provider.c index 654411d..f459e34 100644 --- a/provider.c +++ b/provider.c @@ -214,12 +214,12 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ #endif size_t decoded_len; - if(!auth_header || strncasecmp(auth_header, "oauth", 4) || !sop) { + if(!auth_header || strlen(auth_header) < 6 || strncasecmp(auth_header, "oauth ", 6) || !sop) { zend_string_release(regex); return FAILURE; } /* pass "OAuth " */ - auth_header += 5; + auth_header += 6; #if PHP_VERSION_ID >= 70400 s_auth_header = zend_string_init(auth_header, strlen(auth_header), 0); From 74034bb1dd8a6bf5d52e70d6157f93d25e130f0b Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 22:12:41 -0400 Subject: [PATCH 7/8] address reviews --- oauth.c | 22 +++++++++++++++------- provider.c | 10 +++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/oauth.c b/oauth.c index 2771bc9..f05a95b 100644 --- a/oauth.c +++ b/oauth.c @@ -1732,16 +1732,24 @@ static long oauth_fetch(php_so_object *soo, const char *url, const char *method, #endif } - if (soo->multipart_files_num) { + if (soo->multipart_files || soo->multipart_params) { int mi; for (mi = 0; mi < soo->multipart_files_num; mi++) { - efree(soo->multipart_files[mi]); - efree(soo->multipart_params[mi]); + if (soo->multipart_files) { + efree(soo->multipart_files[mi]); + } + if (soo->multipart_params) { + efree(soo->multipart_params[mi]); + } + } + if (soo->multipart_files) { + efree(soo->multipart_files); + soo->multipart_files = NULL; + } + if (soo->multipart_params) { + efree(soo->multipart_params); + soo->multipart_params = NULL; } - efree(soo->multipart_files); - efree(soo->multipart_params); - soo->multipart_files = NULL; - soo->multipart_params = NULL; soo->multipart_files_num = 0; soo->is_multipart = 0; } diff --git a/provider.c b/provider.c index f459e34..1095791 100644 --- a/provider.c +++ b/provider.c @@ -197,9 +197,9 @@ static inline int oauth_provider_set_param_value(HashTable *ht, char *key, zval Z_TRY_ADDREF_P(val); if (zend_hash_str_update(ht, key, strlen(key), val) == NULL) { Z_TRY_DELREF_P(val); - return FAILURE; + return 0; } - return SUCCESS; + return 1; } /* }}} */ @@ -214,7 +214,7 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ #endif size_t decoded_len; - if(!auth_header || strlen(auth_header) < 6 || strncasecmp(auth_header, "oauth ", 6) || !sop) { + if(!auth_header || strncasecmp(auth_header, "oauth ", 6) || !sop) { zend_string_release(regex); return FAILURE; } @@ -290,7 +290,7 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ ZVAL_STRINGL(&decoded_val, tmp, decoded_len); efree(tmp); - if (oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val)==FAILURE) { + if (!oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val)) { zval_ptr_dtor(&decoded_val); zval_ptr_dtor(&return_value); zval_ptr_dtor(&subpats); @@ -609,7 +609,7 @@ SOP_METHOD(__construct) do { if(zend_hash_get_current_key_ex(Z_ARRVAL_P(params), &key, &num_key, &hpos) == HASH_KEY_IS_STRING) { if((item_param = zend_hash_get_current_data_ex(Z_ARRVAL_P(params), &hpos)) != NULL) { - if(oauth_provider_set_param_value(sop->oauth_params, ZSTR_VAL(key), item_param) == FAILURE) { + if(!oauth_provider_set_param_value(sop->oauth_params, ZSTR_VAL(key), item_param)) { return; } } From f3a7ef0f1583220e47547a0f079a043f27eaf02b Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 22:30:56 -0400 Subject: [PATCH 8/8] address reviews --- provider.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/provider.c b/provider.c index 1095791..295af02 100644 --- a/provider.c +++ b/provider.c @@ -197,9 +197,9 @@ static inline int oauth_provider_set_param_value(HashTable *ht, char *key, zval Z_TRY_ADDREF_P(val); if (zend_hash_str_update(ht, key, strlen(key), val) == NULL) { Z_TRY_DELREF_P(val); - return 0; + return FAILURE; } - return 1; + return SUCCESS; } /* }}} */ @@ -290,7 +290,7 @@ static int oauth_provider_parse_auth_header(php_oauth_provider *sop, char *auth_ ZVAL_STRINGL(&decoded_val, tmp, decoded_len); efree(tmp); - if (!oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val)) { + if (oauth_provider_set_param_value(sop->oauth_params, Z_STRVAL_P(current_param), &decoded_val) == FAILURE) { zval_ptr_dtor(&decoded_val); zval_ptr_dtor(&return_value); zval_ptr_dtor(&subpats); @@ -609,7 +609,7 @@ SOP_METHOD(__construct) do { if(zend_hash_get_current_key_ex(Z_ARRVAL_P(params), &key, &num_key, &hpos) == HASH_KEY_IS_STRING) { if((item_param = zend_hash_get_current_data_ex(Z_ARRVAL_P(params), &hpos)) != NULL) { - if(!oauth_provider_set_param_value(sop->oauth_params, ZSTR_VAL(key), item_param)) { + if(oauth_provider_set_param_value(sop->oauth_params, ZSTR_VAL(key), item_param) == FAILURE) { return; } }