Skip to content

Commit 0216627

Browse files
author
Sterling Hughes
committed
@ Fixed a crash when using the CURLOPT_WRITEHEADER option. (Sterling)
# Folks please test, I've tested a limited amount of test cases, however, # this change is far reaching, so I couldn't test all the necessary things
1 parent 0f3e5a3 commit 0216627

File tree

2 files changed

+91
-59
lines changed

2 files changed

+91
-59
lines changed

ext/curl/curl.c

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,11 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
289289
retval, 2, argv);
290290
if (error == FAILURE) {
291291
php_error(E_WARNING, "Cannot call the CURLOPT_WRITEFUNCTION");
292-
return -1;
292+
length = -1;
293+
}
294+
else {
295+
length = Z_LVAL_P(retval);
293296
}
294-
295-
length = Z_LVAL_P(retval);
296297

297298
zval_ptr_dtor(&argv[0]);
298299
zval_ptr_dtor(&argv[1]);
@@ -341,17 +342,17 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
341342
retval, 3, argv);
342343
if (error == FAILURE) {
343344
php_error(E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
344-
break;
345+
length = -1;
346+
}
347+
else {
348+
memcpy(data, Z_STRVAL_P(retval), size * nmemb);
349+
length = Z_STRLEN_P(retval);
345350
}
346-
347-
memcpy(data, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
348-
length = Z_STRLEN_P(retval);
349351

350352
zval_ptr_dtor(&argv[0]);
351353
zval_ptr_dtor(&argv[1]);
352354
zval_ptr_dtor(&argv[2]);
353355
zval_ptr_dtor(&retval);
354-
355356
break;
356357
}
357358
}
@@ -360,54 +361,73 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
360361
}
361362
/* }}} */
362363

363-
/* {{{ _php_curl_write_header
364+
/* {{{ curl_write_header
364365
*/
365-
static size_t _php_curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
366+
static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
366367
{
367-
php_curl *ch = (php_curl *) ctx;
368-
zval *func = ch->handlers->write_header;
369-
zval *argv[2];
370-
zval *retval;
371-
int error;
372-
int length;
368+
php_curl *ch = (php_curl *) ctx;
369+
php_curl_write *t = ch->handlers->write_header;
370+
int error;
371+
int length;
373372
ELS_FETCH();
373+
374+
switch (t->method) {
375+
case PHP_CURL_STDOUT:
376+
/* Handle special case write when we're returning the entire transfer
377+
*/
378+
if (ch->handlers->write->method == PHP_CURL_RETURN)
379+
smart_str_appendl(&ch->handlers->write->buf, data, size * nmemb);
380+
else
381+
PUTS(data);
382+
break;
383+
case PHP_CURL_FILE:
384+
length = fwrite(data, size, nmemb, t->fp);
385+
break;
386+
case PHP_CURL_USER: {
387+
zval *argv[2];
388+
zval *retval;
389+
390+
MAKE_STD_ZVAL(argv[0]);
391+
MAKE_STD_ZVAL(argv[1]);
392+
MAKE_STD_ZVAL(retval);
374393

375-
MAKE_STD_ZVAL(argv[0]);
376-
MAKE_STD_ZVAL(argv[1]);
377-
MAKE_STD_ZVAL(retval);
394+
ZVAL_RESOURCE(argv[0], ch->id);
395+
zend_list_addref(ch->id);
396+
ZVAL_STRINGL(argv[0], data, size * nmemb, 1);
378397

379-
ZVAL_RESOURCE(argv[0], ch->id);
380-
zend_list_addref(ch->id);
381-
ZVAL_STRINGL(argv[0], data, size * nmemb, 1);
398+
error = call_user_function(EG(function_table),
399+
NULL,
400+
t->func,
401+
retval, 2, argv);
402+
if (error == FAILURE) {
403+
php_error(E_WARNING, "Couldn't call the CURLOPT_HEADERFUNCTION");
404+
length = -1;
405+
}
406+
else {
407+
length = Z_LVAL_P(retval);
408+
}
382409

383-
error = call_user_function(EG(function_table),
384-
NULL,
385-
func,
386-
retval, 2, argv);
387-
if (error == FAILURE) {
388-
php_error(E_WARNING, "Couldn't call the CURLOPT_HEADERFUNCTION");
389-
return -1;
410+
zval_ptr_dtor(&argv[0]);
411+
zval_ptr_dtor(&argv[1]);
412+
zval_ptr_dtor(&retval);
413+
break;
390414
}
391-
392-
length = Z_LVAL_P(retval);
393-
394-
zval_ptr_dtor(&argv[0]);
395-
zval_ptr_dtor(&argv[1]);
396-
zval_ptr_dtor(&retval);
397-
415+
}
416+
398417
return length;
399418
}
400419
/* }}} */
401420

402-
/* {{{ _php_curl_passwd
421+
/* {{{ curl_passwd
403422
*/
404-
static size_t _php_curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
423+
static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
405424
{
406425
php_curl *ch = (php_curl *) ctx;
407426
zval *func = ch->handlers->passwd;
408427
zval *argv[3];
409428
zval *retval;
410429
int error;
430+
int ret = 0;
411431
ELS_FETCH();
412432

413433
MAKE_STD_ZVAL(argv[0]);
@@ -425,22 +445,24 @@ static size_t _php_curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
425445
retval, 2, argv);
426446
if (error == FAILURE) {
427447
php_error(E_WARNING, "Couldn't call the CURLOPT_PASSWDFUNCTION");
428-
return -1;
448+
ret = -1;
429449
}
430-
431-
if (Z_STRLEN_P(retval) > buflen) {
432-
php_error(E_WARNING, "Returned password is too long for libcurl to handle");
433-
return -1;
450+
else {
451+
if (Z_STRLEN_P(retval) > buflen) {
452+
php_error(E_WARNING, "Returned password is too long for libcurl to handle");
453+
ret = -1;
454+
}
455+
else {
456+
strlcpy(buf, Z_STRVAL_P(retval), buflen);
457+
}
434458
}
435-
436-
strlcpy(buf, Z_STRVAL_P(retval), buflen);
437-
459+
438460
zval_ptr_dtor(&argv[0]);
439461
zval_ptr_dtor(&argv[1]);
440462
zval_ptr_dtor(&argv[2]);
441463
zval_ptr_dtor(&retval);
442464

443-
return 0;
465+
return ret;
444466
}
445467
/* }}} */
446468

@@ -483,6 +505,7 @@ static void alloc_curl_handle(php_curl **ch)
483505
*ch = emalloc(sizeof(php_curl));
484506
(*ch)->handlers = ecalloc(1, sizeof(php_curl_handlers));
485507
(*ch)->handlers->write = ecalloc(1, sizeof(php_curl_write));
508+
(*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
486509
(*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read));
487510

488511
zend_llist_init(&(*ch)->to_free.str, sizeof(char *),
@@ -526,6 +549,8 @@ PHP_FUNCTION(curl_init)
526549
curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
527550
curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, curl_read);
528551
curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
552+
curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header);
553+
curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
529554
if (argc > 0) {
530555
char *urlcopy;
531556
convert_to_string_ex(url);
@@ -629,17 +654,24 @@ PHP_FUNCTION(curl_setopt)
629654
FILE *fp;
630655
ZEND_FETCH_RESOURCE(fp, FILE *, zvalue, -1, "File-Handle", php_file_le_fopen());
631656

632-
if (option == CURLOPT_FILE) {
657+
error = CURLE_OK;
658+
switch (option) {
659+
case CURLOPT_FILE:
633660
ch->handlers->write->fp = fp;
634661
ch->handlers->write->method = PHP_CURL_FILE;
635-
}
636-
else if (option == CURLOPT_INFILE) {
662+
break;
663+
case CURLOPT_WRITEHEADER:
664+
ch->handlers->write_header->fp = fp;
665+
ch->handlers->write_header->method = PHP_CURL_FILE;
666+
break;
667+
case CURLOPT_INFILE:
637668
zend_list_addref(Z_LVAL_PP(zvalue));
638669
ch->handlers->read->fp = fp;
639670
ch->handlers->read->fd = Z_LVAL_PP(zvalue);
640-
}
641-
else {
671+
break;
672+
default:
642673
error = curl_easy_setopt(ch->cp, option, fp);
674+
break;
643675
}
644676

645677
break;
@@ -657,7 +689,7 @@ PHP_FUNCTION(curl_setopt)
657689
ch->handlers->write->type = PHP_CURL_BINARY;
658690
case CURLOPT_WRITEFUNCTION:
659691
zval_add_ref(zvalue);
660-
ch->handlers->write->func = *zvalue;
692+
ch->handlers->write->func = *zvalue;
661693
ch->handlers->write->method = PHP_CURL_USER;
662694
break;
663695
case CURLOPT_READFUNCTION:
@@ -667,14 +699,13 @@ PHP_FUNCTION(curl_setopt)
667699
break;
668700
case CURLOPT_HEADERFUNCTION:
669701
zval_add_ref(zvalue);
670-
ch->handlers->write_header = *zvalue;
671-
error = curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, _php_curl_write_header);
672-
error = curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
702+
ch->handlers->write_header->func = *zvalue;
703+
ch->handlers->write_header->method = PHP_CURL_USER;
673704
break;
674705
case CURLOPT_PASSWDFUNCTION:
675706
zval_add_ref(zvalue);
676707
ch->handlers->passwd = *zvalue;
677-
error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, _php_curl_passwd);
708+
error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd);
678709
error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) ch);
679710
break;
680711
case CURLOPT_POSTFIELDS:
@@ -963,10 +994,11 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc)
963994

964995
if (ch->handlers->write->func) zval_ptr_dtor(&ch->handlers->write->func);
965996
if (ch->handlers->read->func) zval_ptr_dtor(&ch->handlers->read->func);
966-
if (ch->handlers->write_header) zval_ptr_dtor(&ch->handlers->write_header);
997+
if (ch->handlers->write_header->func) zval_ptr_dtor(&ch->handlers->write_header->func);
967998
if (ch->handlers->passwd) zval_ptr_dtor(&ch->handlers->passwd);
968999

9691000
efree(ch->handlers->write);
1001+
efree(ch->handlers->write_header);
9701002
efree(ch->handlers->read);
9711003
efree(ch->handlers);
9721004
efree(ch);

ext/curl/php_curl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ typedef struct {
6868

6969
typedef struct {
7070
php_curl_write *write;
71+
php_curl_write *write_header;
7172
php_curl_read *read;
72-
zval *write_header;
7373
zval *passwd;
7474
} php_curl_handlers;
7575

0 commit comments

Comments
 (0)