summaryrefslogtreecommitdiffstats
path: root/bug71488.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bug71488.patch')
-rw-r--r--bug71488.patch80
1 files changed, 80 insertions, 0 deletions
diff --git a/bug71488.patch b/bug71488.patch
new file mode 100644
index 0000000..f4a2609
--- /dev/null
+++ b/bug71488.patch
@@ -0,0 +1,80 @@
+Backported from 5.5 for 5.4 by Remi Collet
+binary patch dropped
+
+From 07c7df68bd68bbe706371fccc77c814ebb335d9e Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 31 Jan 2016 19:37:56 -0800
+Subject: [PATCH] Fixed bug #71488: Stack overflow when decompressing tar
+ archives
+
+---
+ ext/phar/tar.c | 22 ++++++++++++++++------
+ ext/phar/tests/bug71488.phpt | 16 ++++++++++++++++
+ ext/phar/tests/bug71488.tar | Bin 0 -> 10240 bytes
+ 3 files changed, 32 insertions(+), 6 deletions(-)
+ create mode 100644 ext/phar/tests/bug71488.phpt
+ create mode 100644 ext/phar/tests/bug71488.tar
+
+diff --git a/ext/phar/tar.c b/ext/phar/tar.c
+index 5f26805..3a4bd49 100644
+--- a/ext/phar/tar.c
++++ b/ext/phar/tar.c
+@@ -192,6 +192,13 @@ static int phar_tar_process_metadata(pha
+ }
+ /* }}} */
+
++#if !HAVE_STRNLEN
++static size_t strnlen(const char *s, size_t maxlen) {
++ char *r = (char *)memchr(s, '\0', maxlen);
++ return r ? r-s : maxlen;
++}
++#endif
++
+ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, int is_data, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
+ {
+ char buf[512], *actual_alias = NULL, *p;
+@@ -201,6 +208,7 @@ int phar_parse_tarfile(php_stream* fp, c
+ php_uint32 sum1, sum2, size, old;
+ phar_archive_data *myphar, **actual;
+ int last_was_longlink = 0;
++ int linkname_len;
+
+ if (error) {
+ *error = NULL;
+@@ -255,7 +263,7 @@ int phar_parse_tarfile(php_stream* fp, c
+ size = entry.uncompressed_filesize = entry.compressed_filesize =
+ phar_tar_number(hdr->size, sizeof(hdr->size));
+
+- if (((!old && hdr->prefix[0] == 0) || old) && strlen(hdr->name) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
++ if (((!old && hdr->prefix[0] == 0) || old) && strnlen(hdr->name, 100) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
+ off_t curloc;
+
+ if (size > 511) {
+@@ -465,20 +473,22 @@ bail:
+ }
+
+ entry.link = NULL;
+-
++ /* link field is null-terminated unless it has 100 non-null chars.
++ * Thus we can not use strlen. */
++ linkname_len = strnlen(hdr->linkname, 100);
+ if (entry.tar_type == TAR_LINK) {
+- if (!zend_hash_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) {
++ if (!zend_hash_exists(&myphar->manifest, hdr->linkname, linkname_len)) {
+ if (error) {
+- spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
++ spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%.*s\"", fname, linkname_len, hdr->linkname);
+ }
+ pefree(entry.filename, entry.is_persistent);
+ php_stream_close(fp);
+ phar_destroy_phar_data(myphar TSRMLS_CC);
+ return FAILURE;
+ }
+- entry.link = estrdup(hdr->linkname);
++ entry.link = estrndup(hdr->linkname, linkname_len);
+ } else if (entry.tar_type == TAR_SYMLINK) {
+- entry.link = estrdup(hdr->linkname);
++ entry.link = estrndup(hdr->linkname, linkname_len);
+ }
+ phar_set_inode(&entry TSRMLS_CC);
+ zend_hash_add(&myphar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), (void **) &newentry);