diff --git a/ext/phar/phar.c b/ext/phar/phar.c index bb308d898af23..c2184c58d843f 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2374,7 +2374,7 @@ int phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ { uint32_t crc = ~0; - int len = idata->internal_file->uncompressed_filesize; + int len = idata->internal_file->uncompressed_filesize, ret; php_stream *fp = idata->fp; phar_entry_info *entry = idata->internal_file; @@ -2439,13 +2439,11 @@ int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, php_stream_seek(fp, idata->zero, SEEK_SET); - while (len--) { - CRC32(crc, php_stream_getc(fp)); - } + ret = crc32_stream_bulk_update(&crc, fp, len); php_stream_seek(fp, idata->zero, SEEK_SET); - if (~crc == crc32) { + if (SUCCESS == ret && ~crc == crc32) { entry->is_crc_checked = 1; return SUCCESS; } else { @@ -2539,7 +2537,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv zend_off_t manifest_ftell; zend_long offset; size_t wrote; - uint32_t manifest_len, mytime, loc, new_manifest_count; + uint32_t manifest_len, mytime, new_manifest_count; uint32_t newcrc32; php_stream *file, *oldfile, *newfile, *stubfile; php_stream_filter *filter; @@ -2796,10 +2794,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv return EOF; } newcrc32 = ~0; - mytime = entry->uncompressed_filesize; - for (loc = 0;loc < mytime; ++loc) { - CRC32(newcrc32, php_stream_getc(file)); - } + crc32_stream_bulk_update(&newcrc32, file, entry->uncompressed_filesize); entry->crc32 = ~newcrc32; entry->is_crc_checked = 1; if (!(entry->flags & PHAR_ENT_COMPRESSION_MASK)) { diff --git a/ext/phar/zip.c b/ext/phar/zip.c index d1bb6594b32ab..0b0d39c470f10 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -882,7 +882,6 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ /* do extra field for perms later */ if (entry->is_modified) { - uint32_t loc; php_stream_filter *filter; php_stream *efp; @@ -915,9 +914,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ efp = phar_get_efp(entry, 0); newcrc32 = ~0; - for (loc = 0;loc < entry->uncompressed_filesize; ++loc) { - CRC32(newcrc32, php_stream_getc(efp)); - } + crc32_stream_bulk_update(&newcrc32, efp, entry->uncompressed_filesize); entry->crc32 = ~newcrc32; PHAR_SET_32(central.uncompsize, entry->uncompressed_filesize); diff --git a/ext/standard/crc32.c b/ext/standard/crc32.c index 293fab43bbc46..c492a9602c3b5 100644 --- a/ext/standard/crc32.c +++ b/ext/standard/crc32.c @@ -89,24 +89,12 @@ static uint32_t crc32_aarch64(uint32_t crc, char *p, size_t nr) { # endif #endif -/* {{{ Calculate the crc32 polynomial of a string */ -PHP_FUNCTION(crc32) +uint32_t crc32_bulk_update(uint32_t crc, const char *p, size_t nr) { - char *p; - size_t nr; - uint32_t crcinit = 0; - uint32_t crc; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(p, nr) - ZEND_PARSE_PARAMETERS_END(); - - crc = crcinit^0xFFFFFFFF; - #if HAVE_AARCH64_CRC32 if (has_crc32_insn()) { crc = crc32_aarch64(crc, p, nr); - RETURN_LONG(crc^0xFFFFFFFF); + return crc; } #endif @@ -116,9 +104,51 @@ PHP_FUNCTION(crc32) p += nr_simd; #endif + /* The trailing part */ for (; nr--; ++p) { crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF ]; } + + return crc; +} + +int crc32_stream_bulk_update(uint32_t *crc, php_stream *fp, size_t nr) +{ + size_t handled = 0, n; + char buf[1024]; + + while (handled < nr) { + n = nr - handled; + n = (n < sizeof(buf)) ? n : sizeof(buf); /* tweak to buf size */ + + n = php_stream_read(fp, buf, n); + if (n > 0) { + *crc = crc32_bulk_update(*crc, buf, n); + handled += n; + } else { /* EOF */ + return FAILURE; + } + } + + return SUCCESS; +} + +/* {{{ Calculate the crc32 polynomial of a string */ +PHP_FUNCTION(crc32) +{ + char *p; + size_t nr; + uint32_t crcinit = 0; + uint32_t crc; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(p, nr) + ZEND_PARSE_PARAMETERS_END(); + + crc = crcinit^0xFFFFFFFF; + + crc = crc32_bulk_update(crc, p, nr); + RETURN_LONG(crc^0xFFFFFFFF); } /* }}} */ diff --git a/ext/standard/crc32.h b/ext/standard/crc32.h index c6320402b9ad3..262713fd5ec8c 100644 --- a/ext/standard/crc32.h +++ b/ext/standard/crc32.h @@ -23,6 +23,11 @@ #define CRC32(crc, ch) (crc = (crc >> 8) ^ crc32tab[(crc ^ (ch)) & 0xff]) +uint32_t crc32_bulk_update(uint32_t crc, const char *p, size_t nr); + +/* Return FAILURE if stream reading fail */ +int crc32_stream_bulk_update(uint32_t *crc, php_stream *fp, size_t nr); + /* generated using the AUTODIN II polynomial * x^32 + x^26 + x^23 + x^22 + x^16 + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1