-
-
Save smalyshev/7e8403a564c70977a971 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 07c7df68bd68bbe706371fccc77c814ebb335d9e | |
Author: Stanislav Malyshev <stas@php.net> | |
Date: Sun Jan 31 19:37:56 2016 -0800 | |
Fixed bug #71488: Stack overflow when decompressing tar archives | |
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 | |
@@ -195,6 +195,13 @@ static int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp TSRM | |
} | |
/* }}} */ | |
+#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; | |
@@ -204,6 +211,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, | |
php_uint32 sum1, sum2, size, old; | |
phar_archive_data *myphar, **actual; | |
int last_was_longlink = 0; | |
+ int linkname_len; | |
if (error) { | |
*error = NULL; | |
@@ -264,7 +272,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, | |
goto next; | |
} | |
- 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) { | |
@@ -474,20 +482,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); | |
diff --git a/ext/phar/tests/bug71488.phpt b/ext/phar/tests/bug71488.phpt | |
new file mode 100644 | |
index 0000000..05fdd8f | |
--- /dev/null | |
+++ b/ext/phar/tests/bug71488.phpt | |
@@ -0,0 +1,16 @@ | |
+--TEST-- | |
+Phar: bug #71488: Stack overflow when decompressing tar archives | |
+--SKIPIF-- | |
+<?php if (!extension_loaded("phar")) die("skip"); ?> | |
+--FILE-- | |
+<?php | |
+$p = new PharData(__DIR__."/bug71488.tar"); | |
+$newp = $p->decompress("test"); | |
+?> | |
+DONE | |
+--CLEAN-- | |
+<?php | |
+@unlink(__DIR__."/bug71488.test"); | |
+?> | |
+--EXPECT-- | |
+DONE | |
\ No newline at end of file | |
diff --git a/ext/phar/tests/bug71488.tar b/ext/phar/tests/bug71488.tar | |
new file mode 100644 | |
index 0000000..6e14195 | |
Binary files /dev/null and b/ext/phar/tests/bug71488.tar differ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment