Skip to content

Instantly share code, notes, and snippets.

@weltling
Created March 21, 2017 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weltling/aa8dddab3867248df333b24ed3e72398 to your computer and use it in GitHub Desktop.
Save weltling/aa8dddab3867248df333b24ed3e72398 to your computer and use it in GitHub Desktop.
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 394819cf34..d57002a592 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -138,7 +138,8 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
struct zip_file *zf;
struct zip_stat sb;
char b[8192];
- int n, len, ret;
+ zip_int64_t n;
+ int len, ret;
php_stream *stream;
char *fullpath;
char *file_dirname_fullpath;
@@ -255,7 +256,20 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
n = 0;
while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
+#if ZEND_ENABLE_ZVAL_LONG64
php_stream_write(stream, b, n);
+#else
+ size_t k, l;
+ zip_int64_t m = n;
+
+ do {
+ k = m > SIZE_MAX ? SIZE_MAX : (size_t)m;
+
+ l = php_stream_write(stream, b, k);
+
+ m -= l;
+ } while (m > 0);
+#endif
}
php_stream_close(stream);
@@ -1292,7 +1306,7 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_read)
zend_long len = 0;
zip_read_rsrc * zr_rsrc;
zend_string *buffer;
- int n = 0;
+ zip_int64_t n = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) {
return;
@@ -1311,7 +1325,8 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_read)
n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
if (n > 0) {
ZSTR_VAL(buffer)[n] = '\0';
- ZSTR_LEN(buffer) = n;
+ /* On 32-bit, we couldn't read more than were requested, cast should be safe. */
+ ZSTR_LEN(buffer) = (size_t)n;
RETURN_NEW_STR(buffer);
} else {
zend_string_free(buffer);
@@ -1808,7 +1823,7 @@ static ZIPARCHIVE_METHOD(addFromString)
ze_zip_object *ze_obj;
struct zip_source *zs;
int pos = 0;
- int cur_idx;
+ zip_int64_t cur_idx;
if (!self) {
RETURN_FALSE;
@@ -1994,7 +2009,11 @@ static ZIPARCHIVE_METHOD(setArchiveComment)
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &comment, &comment_len) == FAILURE) {
return;
}
- if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
+ if (comment_len > UINT16_MAX) {
+ php_error_docref(NULL, E_WARNING, "Invalid argument, comment is too long, expect a string of max length %u", UINT16_MAX);
+ RETURN_FALSE;
+ }
+ if (zip_set_archive_comment(intern, (const char *)comment, (zip_uint16_t)comment_len)) {
RETURN_FALSE;
} else {
RETURN_TRUE;
@@ -2038,7 +2057,7 @@ static ZIPARCHIVE_METHOD(setCommentName)
zval *self = getThis();
size_t comment_len, name_len;
char * comment, *name;
- int idx;
+ zip_int64_t idx;
if (!self) {
RETURN_FALSE;
@@ -2315,7 +2334,7 @@ static ZIPARCHIVE_METHOD(getCommentName)
struct zip *intern;
zval *self = getThis();
size_t name_len;
- int idx;
+ zip_int64_t idx;
zend_long flags = 0;
int comment_len = 0;
const char * comment;
@@ -2335,14 +2354,18 @@ static ZIPARCHIVE_METHOD(getCommentName)
php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
RETURN_FALSE;
}
+ if (ZEND_LONG_INT_OVFL(flags)) {
+ php_error_docref(NULL, E_NOTICE, "Invalid flags");
+ RETURN_FALSE;
+ }
idx = zip_name_locate(intern, name, 0);
if (idx < 0) {
RETURN_FALSE;
}
- comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
- RETURN_STRINGL((char *)comment, (zend_long)comment_len);
+ comment = zip_get_file_comment(intern, idx, &comment_len, flags);
+ RETURN_STRINGL((char *)comment, comment_len);
}
/* }}} */
@@ -2781,11 +2804,12 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
zend_long index = -1;
zend_long flags = 0;
zend_long len = 0;
+ size_t alloc_len = 0;
zend_string *filename;
zend_string *buffer;
- int n = 0;
+ zip_int64_t n = 0;
if (!self) {
RETURN_FALSE;
@@ -2810,7 +2834,10 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
}
if (len < 1) {
- len = sb.size;
+ /* FIXME not safe on 32-bit. */
+ alloc_len = sb.size;
+ } else {
+ alloc_len = len;
}
if (index >= 0) {
zf = zip_fopen_index(intern, index, flags);
@@ -2822,7 +2849,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
RETURN_FALSE;
}
- buffer = zend_string_safe_alloc(1, len, 0, 0);
+ buffer = zend_string_safe_alloc(1, alloc_len, 0, 0);
n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
if (n < 1) {
zend_string_free(buffer);
@@ -2831,7 +2858,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
zip_fclose(zf);
ZSTR_VAL(buffer)[n] = '\0';
- ZSTR_LEN(buffer) = n;
+ ZSTR_LEN(buffer) = (size_t)n;
RETURN_NEW_STR(buffer);
}
/* }}} */
diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h
index 327ad54262..c1a6815f2d 100644
--- a/ext/zip/php_zip.h
+++ b/ext/zip/php_zip.h
@@ -43,8 +43,8 @@ extern zend_module_entry zip_module_entry;
typedef struct _ze_zip_rsrc {
struct zip *za;
- int index_current;
- int num_files;
+ zip_uint64_t index_current;
+ zip_uint64_t num_files;
} zip_rsrc;
typedef zip_rsrc * zip_rsrc_ptr;
diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c
index 2ed584021d..5cad2d7bce 100644
--- a/ext/zip/zip_stream.c
+++ b/ext/zip/zip_stream.c
@@ -44,7 +44,7 @@ struct php_zip_stream_data_t {
/* {{{ php_zip_ops_read */
static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count)
{
- ssize_t n = 0;
+ zip_int64_t n = 0;
STREAM_DATA_FROM_STREAM();
if (self->za && self->zf) {
@@ -66,10 +66,11 @@ static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count)
}
/* cast count to signed value to avoid possibly negative n
* being cast to unsigned value */
- if (n == 0 || n < (ssize_t)count) {
+ if (n == 0 || n < count) {
stream->eof = 1;
} else {
- self->cursor += n;
+ /* On 32-bit, only SIZE_MAX bytes can be read, so it is safe to cast. */
+ self->cursor += (size_t)n;
}
}
return (n < 1 ? 0 : (size_t)n);
@@ -173,6 +174,7 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{
zip_close(za);
if (path[path_len-1] != '/') {
+ /* FIXME not safe on 32-bit. */
ssb->sb.st_size = sb.size;
ssb->sb.st_mode |= S_IFREG; /* regular file */
} else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment