{"task":"Diagnose this reproduced PHP 8.2.34 upload-progress regression using the selected original C excerpts. A benign multipart body is 262642 bytes: two files followed by another large form field. With session.upload_progress.cleanup=0, freq=1 and min_freq=0, the final session array has done=true but bytes_processed=136576. File byte counts are correct. Explain the concrete source-level operation that makes this final counter stale, citing original source lines. Propose a minimal unified diff to make the final counter equal the body length while preserving progress, cleanup and cancellation. State what the test establishes and what it cannot establish. Include the diagnosis, patch and regression expectation within the output limit.","answer_language":"Spanish","file":"php82_session_excerpt.c.txt","lines":[{"line":1,"text":"/* Selected, non-contiguous excerpts from PHP 8.2.34. Not a standalone C file. */"},{"line":2,"text":""},{"line":3,"text":"/*"},{"line":4,"text":"   +----------------------------------------------------------------------+"},{"line":5,"text":"   | Copyright (c) The PHP Group                                          |"},{"line":6,"text":"   +----------------------------------------------------------------------+"},{"line":7,"text":"   | This source file is subject to version 3.01 of the PHP license,      |"},{"line":8,"text":"   | that is bundled with this package in the file LICENSE, and is        |"},{"line":9,"text":"   | available through the world-wide-web at the following url:           |"},{"line":10,"text":"   | https://www.php.net/license/3_01.txt                                 |"},{"line":11,"text":"   | If you did not receive a copy of the PHP license and are unable to   |"},{"line":12,"text":"   | obtain it through the world-wide-web, please send a note to          |"},{"line":13,"text":"   | license@php.net so we can mail you a copy immediately.               |"},{"line":14,"text":"   +----------------------------------------------------------------------+"},{"line":15,"text":"   | Authors: Sascha Schumann <sascha@schumann.cx>                        |"},{"line":16,"text":"   |          Andrei Zmievski <andrei@php.net>                            |"},{"line":17,"text":"   +----------------------------------------------------------------------+"},{"line":18,"text":" */"},{"line":19,"text":""},{"line":20,"text":"#line 123 \"ext/session/php_session.h\""},{"line":21,"text":"typedef struct _php_session_rfc1867_progress {"},{"line":22,"text":"\tsize_t    sname_len;"},{"line":23,"text":"\tzval      sid;"},{"line":24,"text":"\tsmart_str key;"},{"line":25,"text":""},{"line":26,"text":"\tzend_long      update_step;"},{"line":27,"text":"\tzend_long      next_update;"},{"line":28,"text":"\tdouble    next_update_time;"},{"line":29,"text":"\tbool cancel_upload;"},{"line":30,"text":"\tbool apply_trans_sid;"},{"line":31,"text":"\tsize_t    content_length;"},{"line":32,"text":""},{"line":33,"text":"\tzval      data;                 /* the array exported to session data */"},{"line":34,"text":"\tzval\t *post_bytes_processed; /* data[\"bytes_processed\"] */"},{"line":35,"text":"\tzval      files;                /* data[\"files\"] array */"},{"line":36,"text":"\tzval      current_file;         /* array of currently uploading file */"},{"line":37,"text":"\tzval\t *current_file_bytes_processed;"},{"line":38,"text":"} php_session_rfc1867_progress;"},{"line":39,"text":""},{"line":40,"text":"#line 2960 \"ext/session/session.c\""},{"line":41,"text":"static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, int force_update) /* {{{ */"},{"line":42,"text":"{"},{"line":43,"text":"\tif (!force_update) {"},{"line":44,"text":"\t\tif (Z_LVAL_P(progress->post_bytes_processed) < progress->next_update) {"},{"line":45,"text":"\t\t\treturn;"},{"line":46,"text":"\t\t}"},{"line":47,"text":"#ifdef HAVE_GETTIMEOFDAY"},{"line":48,"text":"\t\tif (PS(rfc1867_min_freq) > 0.0) {"},{"line":49,"text":"\t\t\tstruct timeval tv = {0};"},{"line":50,"text":"\t\t\tdouble dtv;"},{"line":51,"text":"\t\t\tgettimeofday(&tv, NULL);"},{"line":52,"text":"\t\t\tdtv = (double) tv.tv_sec + tv.tv_usec / 1000000.0;"},{"line":53,"text":"\t\t\tif (dtv < progress->next_update_time) {"},{"line":54,"text":"\t\t\t\treturn;"},{"line":55,"text":"\t\t\t}"},{"line":56,"text":"\t\t\tprogress->next_update_time = dtv + PS(rfc1867_min_freq);"},{"line":57,"text":"\t\t}"},{"line":58,"text":"#endif"},{"line":59,"text":"\t\tprogress->next_update = Z_LVAL_P(progress->post_bytes_processed) + progress->update_step;"},{"line":60,"text":"\t}"},{"line":61,"text":""},{"line":62,"text":"\tphp_session_initialize();"},{"line":63,"text":"\tPS(session_status) = php_session_active;"},{"line":64,"text":"\tIF_SESSION_VARS() {"},{"line":65,"text":"\t\tzval *sess_var = Z_REFVAL(PS(http_session_vars));"},{"line":66,"text":"\t\tSEPARATE_ARRAY(sess_var);"},{"line":67,"text":""},{"line":68,"text":"\t\tprogress->cancel_upload |= php_check_cancel_upload(progress);"},{"line":69,"text":"\t\tZ_TRY_ADDREF(progress->data);"},{"line":70,"text":"\t\tzend_hash_update(Z_ARRVAL_P(sess_var), progress->key.s, &progress->data);"},{"line":71,"text":"\t}"},{"line":72,"text":"\tphp_session_flush(1);"},{"line":73,"text":"} /* }}} */"},{"line":74,"text":""},{"line":75,"text":"#line 3083 \"ext/session/session.c\""},{"line":76,"text":"\t\t\t\tarray_init(&progress->files);"},{"line":77,"text":""},{"line":78,"text":"\t\t\t\tadd_assoc_long_ex(&progress->data, \"start_time\", sizeof(\"start_time\") - 1, (zend_long)sapi_get_request_time());"},{"line":79,"text":"\t\t\t\tadd_assoc_long_ex(&progress->data, \"content_length\",  sizeof(\"content_length\") - 1, progress->content_length);"},{"line":80,"text":"\t\t\t\tadd_assoc_long_ex(&progress->data, \"bytes_processed\", sizeof(\"bytes_processed\") - 1, data->post_bytes_processed);"},{"line":81,"text":"\t\t\t\tadd_assoc_bool_ex(&progress->data, \"done\", sizeof(\"done\") - 1, 0);"},{"line":82,"text":"\t\t\t\tadd_assoc_zval_ex(&progress->data, \"files\", sizeof(\"files\") - 1, &progress->files);"},{"line":83,"text":""},{"line":84,"text":"\t\t\t\tprogress->post_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->data), \"bytes_processed\", sizeof(\"bytes_processed\") - 1);"},{"line":85,"text":""},{"line":86,"text":""},{"line":87,"text":"#line 3103 \"ext/session/session.c\""},{"line":88,"text":"\t\t\tarray_init(&progress->current_file);"},{"line":89,"text":""},{"line":90,"text":"\t\t\t/* Each uploaded file has its own array. Trying to make it close to $_FILES entries. */"},{"line":91,"text":"\t\t\tadd_assoc_string_ex(&progress->current_file, \"field_name\", sizeof(\"field_name\") - 1, data->name);"},{"line":92,"text":"\t\t\tadd_assoc_string_ex(&progress->current_file, \"name\", sizeof(\"name\") - 1, *data->filename);"},{"line":93,"text":"\t\t\tadd_assoc_null_ex(&progress->current_file, \"tmp_name\", sizeof(\"tmp_name\") - 1);"},{"line":94,"text":"\t\t\tadd_assoc_long_ex(&progress->current_file, \"error\", sizeof(\"error\") - 1, 0);"},{"line":95,"text":""},{"line":96,"text":"\t\t\tadd_assoc_bool_ex(&progress->current_file, \"done\", sizeof(\"done\") - 1, 0);"},{"line":97,"text":"\t\t\tadd_assoc_long_ex(&progress->current_file, \"start_time\", sizeof(\"start_time\") - 1, (zend_long)time(NULL));"},{"line":98,"text":"\t\t\tadd_assoc_long_ex(&progress->current_file, \"bytes_processed\", sizeof(\"bytes_processed\") - 1, 0);"},{"line":99,"text":""},{"line":100,"text":"\t\t\tadd_next_index_zval(&progress->files, &progress->current_file);"},{"line":101,"text":""},{"line":102,"text":"\t\t\tprogress->current_file_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->current_file), \"bytes_processed\", sizeof(\"bytes_processed\") - 1);"},{"line":103,"text":""},{"line":104,"text":"\t\t\tZ_LVAL_P(progress->current_file_bytes_processed) =  data->post_bytes_processed;"},{"line":105,"text":"\t\t\tphp_session_rfc1867_update(progress, 0);"},{"line":106,"text":"\t\t}"},{"line":107,"text":"\t\tbreak;"},{"line":108,"text":"\t\tcase MULTIPART_EVENT_FILE_DATA: {"},{"line":109,"text":"\t\t\tmultipart_event_file_data *data = (multipart_event_file_data *) event_data;"},{"line":110,"text":""},{"line":111,"text":"\t\t\tif (!Z_TYPE(progress->sid) || !progress->key.s) {"},{"line":112,"text":"\t\t\t\tbreak;"},{"line":113,"text":"\t\t\t}"},{"line":114,"text":""},{"line":115,"text":"\t\t\tZ_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length;"},{"line":116,"text":"\t\t\tZ_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;"},{"line":117,"text":""},{"line":118,"text":"\t\t\tphp_session_rfc1867_update(progress, 0);"},{"line":119,"text":"\t\t}"},{"line":120,"text":""},{"line":121,"text":"#line 3147 \"ext/session/session.c\""},{"line":122,"text":"\t\t\tadd_assoc_long_ex(&progress->current_file, \"error\", sizeof(\"error\") - 1, data->cancel_upload);"},{"line":123,"text":"\t\t\tadd_assoc_bool_ex(&progress->current_file, \"done\", sizeof(\"done\") - 1,  1);"},{"line":124,"text":""},{"line":125,"text":"\t\t\tZ_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;"},{"line":126,"text":""},{"line":127,"text":"\t\t\tphp_session_rfc1867_update(progress, 0);"},{"line":128,"text":"\t\t}"},{"line":129,"text":"\t\tbreak;"},{"line":130,"text":"\t\tcase MULTIPART_EVENT_END: {"},{"line":131,"text":"\t\t\tmultipart_event_end *data = (multipart_event_end *) event_data;"},{"line":132,"text":""},{"line":133,"text":"\t\t\tif (Z_TYPE(progress->sid) && progress->key.s) {"},{"line":134,"text":"\t\t\t\tif (PS(rfc1867_cleanup)) {"},{"line":135,"text":"\t\t\t\t\tphp_session_rfc1867_cleanup(progress);"},{"line":136,"text":"\t\t\t\t} else {"},{"line":137,"text":"\t\t\t\t\tif (!Z_ISUNDEF(progress->data)) {"},{"line":138,"text":"\t\t\t\t\t\tSEPARATE_ARRAY(&progress->data);"},{"line":139,"text":"\t\t\t\t\t\tadd_assoc_bool_ex(&progress->data, \"done\", sizeof(\"done\") - 1, 1);"},{"line":140,"text":"\t\t\t\t\t\tZ_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;"},{"line":141,"text":"\t\t\t\t\t\tphp_session_rfc1867_update(progress, 1);"},{"line":142,"text":"\t\t\t\t\t}"},{"line":143,"text":"\t\t\t\t}"},{"line":144,"text":"\t\t\t\tphp_rshutdown_session_globals();"},{"line":145,"text":"\t\t\t}"},{"line":146,"text":""},{"line":147,"text":"\t\t\tif (!Z_ISUNDEF(progress->data)) {"},{"line":148,"text":"\t\t\t\tzval_ptr_dtor(&progress->data);"},{"line":149,"text":"\t\t\t}"},{"line":150,"text":"\t\t\tzval_ptr_dtor(&progress->sid);"},{"line":151,"text":"\t\t\tsmart_str_free(&progress->key);"},{"line":152,"text":"\t\t\tefree(progress);"},{"line":153,"text":"\t\t\tprogress = NULL;"},{"line":154,"text":"\t\t\tPS(rfc1867_progress) = NULL;"},{"line":155,"text":"\t\t}"}]}
