From da12553709e05dd58413dcad150fb7b60689dc00 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 17:49:00 -0400 Subject: [PATCH 1/7] Fixes #37 --- oauth.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/oauth.c b/oauth.c index a424097..e77ae17 100644 --- a/oauth.c +++ b/oauth.c @@ -1061,6 +1061,9 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl CURLcode cres, ctres, crres; CURL *curl; struct curl_slist *curl_headers = NULL; +#if LIBCURL_VERSION_NUM >= 0x073800 + curl_mime *mime = NULL; +#endif long l_code, response_code = -1; double d_code; zval info, *zca_info, *zca_path, *cur_val; @@ -1106,12 +1109,13 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl } if(soo->is_multipart) { - struct curl_httppost *ff = NULL; - struct curl_httppost *lf = NULL; +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ + mime = curl_mime_init(curl); int i; for(i=0; i < soo->multipart_files_num; i++) { char *type, *filename, *postval; + curl_mimepart *part; /* swiped from ext/curl/interface.c to help with consistency */ postval = estrdup(soo->multipart_files[i]); @@ -1129,6 +1133,49 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl } /* open_basedir check */ + if(php_check_open_basedir(postval)) { + char *em; + spprintf(&em, 0, "failed to open file for multipart request: %s", postval); + soo_handle_error(soo, -1, em, NULL, NULL); + efree(em); + curl_mime_free(mime); + return 1; + } + + part = curl_mime_addpart(mime); + curl_mime_name(part, soo->multipart_params[i]); + curl_mime_filedata(part, postval); + curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : soo->multipart_files[i]); + curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); + } else { + part = curl_mime_addpart(mime); + curl_mime_name(part, soo->multipart_params[i]); + curl_mime_data(part, postval, CURL_ZERO_TERMINATED); + } + } + + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); +#else + struct curl_httppost *ff = NULL; + struct curl_httppost *lf = NULL; + int i; + + for(i=0; i < soo->multipart_files_num; i++) { + char *type, *filename, *postval; + + postval = estrdup(soo->multipart_files[i]); + + if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { + ++soo->multipart_params[i]; + ++postval; + + if((type = (char *) php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { + *type = '\0'; + } + if((filename = (char *) php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) { + *filename = '\0'; + } + if(php_check_open_basedir(postval)) { char *em; spprintf(&em, 0, "failed to open file for multipart request: %s", postval); @@ -1155,6 +1202,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl } curl_easy_setopt(curl, CURLOPT_HTTPPOST, ff); +#endif } else if (payload->len) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload->c); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload->len); @@ -1307,6 +1355,11 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL); efree(bufz); } +#if LIBCURL_VERSION_NUM >= 0x073800 + if (mime) { + curl_mime_free(mime); + } +#endif curl_easy_cleanup(curl); return response_code; } From 69f54645591f89f4dce32507ce1f90b0ab1573ad Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 17:57:20 -0400 Subject: [PATCH 2/7] address reviews --- oauth.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/oauth.c b/oauth.c index e77ae17..f4c6bce 100644 --- a/oauth.c +++ b/oauth.c @@ -1063,6 +1063,9 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl struct curl_slist *curl_headers = NULL; #if LIBCURL_VERSION_NUM >= 0x073800 curl_mime *mime = NULL; +#else + struct curl_httppost *ff = NULL; + struct curl_httppost *lf = NULL; #endif long l_code, response_code = -1; double d_code; @@ -1110,9 +1113,14 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl if(soo->is_multipart) { #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ - mime = curl_mime_init(curl); int i; + mime = curl_mime_init(curl); + if (!mime) { + soo_handle_error(soo, -1, "failed to initialize curl mime", NULL, NULL); + goto cleanup; + } + for(i=0; i < soo->multipart_files_num; i++) { char *type, *filename, *postval; curl_mimepart *part; @@ -1138,17 +1146,24 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL); efree(em); - curl_mime_free(mime); - return 1; + goto cleanup; } part = curl_mime_addpart(mime); + if (!part) { + soo_handle_error(soo, -1, "failed to add curl mime part", NULL, NULL); + goto cleanup; + } curl_mime_name(part, soo->multipart_params[i]); curl_mime_filedata(part, postval); - curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : soo->multipart_files[i]); + curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : postval); curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); } else { part = curl_mime_addpart(mime); + if (!part) { + soo_handle_error(soo, -1, "failed to add curl mime part", NULL, NULL); + goto cleanup; + } curl_mime_name(part, soo->multipart_params[i]); curl_mime_data(part, postval, CURL_ZERO_TERMINATED); } @@ -1156,8 +1171,6 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); #else - struct curl_httppost *ff = NULL; - struct curl_httppost *lf = NULL; int i; for(i=0; i < soo->multipart_files_num; i++) { @@ -1181,13 +1194,13 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL); efree(em); - return 1; + goto cleanup; } curl_formadd(&ff, &lf, CURLFORM_COPYNAME, soo->multipart_params[i], CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), - CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : soo->multipart_files[i], + CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval, CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", CURLFORM_FILE, postval, CURLFORM_END); @@ -1355,10 +1368,15 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL); efree(bufz); } +cleanup: #if LIBCURL_VERSION_NUM >= 0x073800 if (mime) { curl_mime_free(mime); } +#else + if (ff) { + curl_formfree(ff); + } #endif curl_easy_cleanup(curl); return response_code; From 03db04a055b0bbbf3223efdf925d80bbfb77ac2d Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 18:05:13 -0400 Subject: [PATCH 3/7] address reviews --- oauth.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/oauth.c b/oauth.c index f4c6bce..89b0372 100644 --- a/oauth.c +++ b/oauth.c @@ -1114,6 +1114,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl if(soo->is_multipart) { #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ int i; + CURLcode mres; mime = curl_mime_init(curl); if (!mime) { @@ -1122,11 +1123,11 @@ 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, *filename, *postval; + char *type, *filename, *postval, *postval_orig; curl_mimepart *part; /* swiped from ext/curl/interface.c to help with consistency */ - postval = estrdup(soo->multipart_files[i]); + postval_orig = postval = estrdup(soo->multipart_files[i]); if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { /* :< (chomp) @ */ @@ -1146,27 +1147,41 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL); efree(em); + efree(postval_orig); goto cleanup; } part = curl_mime_addpart(mime); if (!part) { soo_handle_error(soo, -1, "failed to add curl mime part", NULL, NULL); + efree(postval_orig); + goto cleanup; + } + mres = curl_mime_name(part, soo->multipart_params[i]); + if (mres == CURLE_OK) mres = curl_mime_filedata(part, postval); + if (mres == CURLE_OK) mres = curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : postval); + if (mres == CURLE_OK) mres = curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); + if (mres != CURLE_OK) { + soo_handle_error(soo, -1, "failed to set curl mime part data", NULL, NULL); + efree(postval_orig); goto cleanup; } - curl_mime_name(part, soo->multipart_params[i]); - curl_mime_filedata(part, postval); - curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : postval); - curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); } else { part = curl_mime_addpart(mime); if (!part) { soo_handle_error(soo, -1, "failed to add curl mime part", NULL, NULL); + efree(postval_orig); + goto cleanup; + } + mres = curl_mime_name(part, soo->multipart_params[i]); + if (mres == CURLE_OK) mres = curl_mime_data(part, postval, CURL_ZERO_TERMINATED); + if (mres != CURLE_OK) { + soo_handle_error(soo, -1, "failed to set curl mime part data", NULL, NULL); + efree(postval_orig); goto cleanup; } - curl_mime_name(part, soo->multipart_params[i]); - curl_mime_data(part, postval, CURL_ZERO_TERMINATED); } + efree(postval_orig); } curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); @@ -1174,9 +1189,9 @@ 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, *filename, *postval; + char *type, *filename, *postval, *postval_orig; - postval = estrdup(soo->multipart_files[i]); + postval_orig = postval = estrdup(soo->multipart_files[i]); if (postval[0] == '@' && soo->multipart_params[i][0] == '@') { ++soo->multipart_params[i]; @@ -1194,6 +1209,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl spprintf(&em, 0, "failed to open file for multipart request: %s", postval); soo_handle_error(soo, -1, em, NULL, NULL); efree(em); + efree(postval_orig); goto cleanup; } @@ -1212,6 +1228,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl CURLFORM_CONTENTSLENGTH, (long)strlen(postval), CURLFORM_END); } + efree(postval_orig); } curl_easy_setopt(curl, CURLOPT_HTTPPOST, ff); @@ -1283,10 +1300,6 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl smart_string_0(&soo->lastresponse); smart_string_0(&soo->headers_in); - if (curl_headers) { - curl_slist_free_all(curl_headers); - } - if (CURLE_OK == cres) { ctres = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type); crres = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); @@ -1369,6 +1382,9 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl efree(bufz); } cleanup: + if (curl_headers) { + curl_slist_free_all(curl_headers); + } #if LIBCURL_VERSION_NUM >= 0x073800 if (mime) { curl_mime_free(mime); From 397b7cded7329665e7b7089a4fd376305e82e61f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 18:27:27 -0400 Subject: [PATCH 4/7] address reviews --- oauth.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/oauth.c b/oauth.c index 89b0372..f1b28fe 100644 --- a/oauth.c +++ b/oauth.c @@ -1162,7 +1162,10 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl if (mres == CURLE_OK) mres = curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : postval); if (mres == CURLE_OK) mres = curl_mime_type(part, type ? type + sizeof(";type=") - 1 : "application/octet-stream"); if (mres != CURLE_OK) { - soo_handle_error(soo, -1, "failed to set curl mime part data", NULL, NULL); + char *em; + spprintf(&em, 0, "failed to set curl mime part data (%s)", curl_easy_strerror(mres)); + soo_handle_error(soo, -1, em, NULL, NULL); + efree(em); efree(postval_orig); goto cleanup; } @@ -1176,7 +1179,10 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl mres = curl_mime_name(part, soo->multipart_params[i]); if (mres == CURLE_OK) mres = curl_mime_data(part, postval, CURL_ZERO_TERMINATED); if (mres != CURLE_OK) { - soo_handle_error(soo, -1, "failed to set curl mime part data", NULL, NULL); + char *em; + spprintf(&em, 0, "failed to set curl mime part data (%s)", curl_easy_strerror(mres)); + soo_handle_error(soo, -1, em, NULL, NULL); + efree(em); efree(postval_orig); goto cleanup; } From b1eb638ec1c60b110d349ec5011c0e9bb210c05d Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 18:33:55 -0400 Subject: [PATCH 5/7] address reviews --- oauth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oauth.c b/oauth.c index f1b28fe..c8a9f73 100644 --- a/oauth.c +++ b/oauth.c @@ -1123,7 +1123,7 @@ 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, *filename, *postval, *postval_orig; + char *type = NULL, *filename = NULL, *postval, *postval_orig; curl_mimepart *part; /* swiped from ext/curl/interface.c to help with consistency */ @@ -1195,7 +1195,7 @@ 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, *filename, *postval, *postval_orig; + char *type = NULL, *filename = NULL, *postval, *postval_orig; postval_orig = postval = estrdup(soo->multipart_files[i]); From bf51022d00f44b0a1056e0a3f9020cc8e91b5332 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 18:45:16 -0400 Subject: [PATCH 6/7] address reviews --- oauth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/oauth.c b/oauth.c index c8a9f73..7456db5 100644 --- a/oauth.c +++ b/oauth.c @@ -1082,6 +1082,10 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl sslcheck = soo->sslcheck; curl = curl_easy_init(); + if (!curl) { + soo_handle_error(soo, -1, "failed to initialize curl", NULL, NULL); + return -1; + } if (request_headers) { for (zend_hash_internal_pointer_reset_ex(request_headers, &pos); From 24d83645b081a9cac808a401cd9a399a1fc92529 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Sat, 4 Apr 2026 18:52:45 -0400 Subject: [PATCH 7/7] address reviews --- oauth.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/oauth.c b/oauth.c index 7456db5..f1c1c35 100644 --- a/oauth.c +++ b/oauth.c @@ -1163,7 +1163,7 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl } mres = curl_mime_name(part, soo->multipart_params[i]); if (mres == CURLE_OK) mres = curl_mime_filedata(part, postval); - if (mres == CURLE_OK) mres = curl_mime_filename(part, filename ? filename + sizeof(";filename=") - 1 : 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"); if (mres != CURLE_OK) { char *em; @@ -1223,13 +1223,22 @@ long make_req_curl(php_so_object *soo, const char *url, const smart_string *payl goto cleanup; } - curl_formadd(&ff, &lf, - CURLFORM_COPYNAME, soo->multipart_params[i], - CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), - CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval, - CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", - CURLFORM_FILE, postval, - CURLFORM_END); + if (filename) { + curl_formadd(&ff, &lf, + CURLFORM_COPYNAME, soo->multipart_params[i], + CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]), + 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_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],