1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) { static const char token[] = "__HALT_COMPILER();"; static const char zip_magic[] = "PK\x03\x04"; static const char gz_magic[] = "\x1f\x8b\x08"; static const char bz_magic[] = "BZh"; char *pos, test = '\0'; int recursion_count = 3; const int window_size = 1024; char buffer[1024 + sizeof(token)]; const zend_long readsize = sizeof(buffer) - sizeof(token); const zend_long tokenlen = sizeof(token) - 1; zend_long halt_offset; size_t got; uint32_t compression = PHAR_FILE_COMPRESSED_NONE;
if (error) { *error = NULL; }
if (-1 == php_stream_rewind(fp)) { MAPPHAR_ALLOC_FAIL("cannot rewind phar \"%s\"") }
buffer[sizeof(buffer)-1] = '\0'; memset(buffer, 32, sizeof(token)); halt_offset = 0;
while(!php_stream_eof(fp)) { if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < (size_t) tokenlen) { MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") }
if (!test && recursion_count) { test = '\1'; pos = buffer+tokenlen; if (!memcmp(pos, gz_magic, 3)) { char err = 0; php_stream_filter *filter; php_stream *temp; zval filterparams;
if (!PHAR_G(has_zlib)) { MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini") } array_init(&filterparams);
#ifndef MAX_WBITS #define MAX_WBITS 15 #endif add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS + 32);
if (!(temp = php_stream_fopen_tmpfile())) { MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"") }
php_stream_rewind(fp); filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp));
if (!filter) { err = 1; add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS); filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp)); zend_array_destroy(Z_ARR(filterparams));
if (!filter) { php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6") } } else { zend_array_destroy(Z_ARR(filterparams)); }
php_stream_filter_append(&temp->writefilters, filter);
if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { php_stream_filter_remove(filter, 1); if (err) { php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6") } php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file") }
php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1); php_stream_close(fp); fp = temp; php_stream_rewind(fp); compression = PHAR_FILE_COMPRESSED_GZ;
test = '\0'; if (!--recursion_count) { MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\""); break; } continue; } else if (!memcmp(pos, bz_magic, 3)) { php_stream_filter *filter; php_stream *temp;
if (!PHAR_G(has_bz2)) { MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file, enable bz2 extension in php.ini") }
if (!(temp = php_stream_fopen_tmpfile())) { MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of bzipped phar archive \"%s\"") }
php_stream_rewind(fp); filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp));
if (!filter) { php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\", filter creation failed") }
php_stream_filter_append(&temp->writefilters, filter);
if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { php_stream_filter_remove(filter, 1); php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file") }
php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1); php_stream_close(fp); fp = temp; php_stream_rewind(fp); compression = PHAR_FILE_COMPRESSED_BZ2;
test = '\0'; if (!--recursion_count) { MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\""); break; } continue; }
if (!memcmp(pos, zip_magic, 4)) { php_stream_seek(fp, 0, SEEK_END); return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error); }
if (got >= 512) { if (phar_is_tar(pos, fname)) { php_stream_rewind(fp); return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, compression, error); } } }
if (got > 0 && (pos = phar_strnstr(buffer, got + sizeof(token), token, sizeof(token)-1)) != NULL) { halt_offset += (pos - buffer); return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error); }
halt_offset += got; memmove(buffer, buffer + window_size, tokenlen); }
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (__HALT_COMPILER(); not found)") }
|