cellog                                   Fri, 24 Jul 2009 19:40:41 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=284716

Log:
fix --CLEAN-- of all.phpt, remove unnecessary check in phar_convert_again.phpt, 
and fix signature generation and checking for zip to also include central 
directory up to the signature, implement better check for end-of-zip at 
signature verification

Changed paths:
    U   pecl/phar/trunk/tests/phar_convert_again.phpt
    U   pecl/phar/trunk/tests/zip/all.phpt
    U   pecl/phar/trunk/zip.c
    U   php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt
    U   php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt
    U   php/php-src/branches/PHP_5_3/ext/phar/zip.c
    U   php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt
    U   php/php-src/trunk/ext/phar/tests/zip/all.phpt
    U   php/php-src/trunk/ext/phar/zip.c

Modified: pecl/phar/trunk/tests/phar_convert_again.phpt
===================================================================
--- pecl/phar/trunk/tests/phar_convert_again.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ pecl/phar/trunk/tests/phar_convert_again.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -62,11 +62,6 @@
 } catch (Exception $e) {
 echo $e->getMessage() . "\n";
 }
-try {
-$data->setSignatureAlgorithm(Phar::MD5);
-} catch (Exception $e) {
-echo $e->getMessage() . "\n";
-}
 $tar = $phar->convertToExecutable(Phar::TAR);
 echo $tar->getPath() . "\n";
 $data = $tar->convertToData();
@@ -188,7 +183,6 @@
 A Phar stub cannot be set in a plain zip archive
 A Phar stub cannot be set in a plain zip archive
 A Phar alias cannot be set in a plain zip archive
-Cannot set signature algorithm, not possible with zip-based phar archives
 %sphar_convert_again2.phar.tar
 %sphar_convert_again2.tar
 %sphar_convert_again2.phar.tar.gz

Modified: pecl/phar/trunk/tests/zip/all.phpt
===================================================================
--- pecl/phar/trunk/tests/zip/all.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ pecl/phar/trunk/tests/zip/all.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -46,6 +46,7 @@
 ?>
 ===DONE===
 --CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?>
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?>
 --EXPECT--
 bool(false)

Modified: pecl/phar/trunk/zip.c
===================================================================
--- pecl/phar/trunk/zip.c	2009-07-24 19:21:10 UTC (rev 284715)
+++ pecl/phar/trunk/zip.c	2009-07-24 19:40:41 UTC (rev 284716)
@@ -350,6 +350,7 @@
 	/* add each central directory item to the manifest */
 	for (i = 0; i < PHAR_GET_16(locator.count); ++i) {
 		phar_zip_central_dir_file zipentry;
+		off_t beforeus = php_stream_tell(fp);

 		if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) {
 			PHAR_ZIP_FAIL("unable to read central directory entry, truncated");
@@ -404,24 +405,34 @@
 		if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
 			size_t read;
 			php_stream *sigfile;
+			off_t now;
+			char *sig;

+			now = php_stream_tell(fp);
 			pefree(entry.filename, entry.is_persistent);
 			sigfile = php_stream_fopen_tmpfile();

 			php_stream_seek(fp, 0, SEEK_SET);
 			/* copy file contents + local headers and zip comment, if any, to be hashed for signature */
 			phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL);
+			/* seek to central directory */
+			php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
+			/* copy central directory header */
+			phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL);
 			if (metadata) {
 				php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len));
 			}
 			php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
-			read = php_stream_read(fp, buf, entry.uncompressed_filesize);
+			sig = (char *) emalloc(entry.uncompressed_filesize);
+			read = php_stream_read(fp, sig, entry.uncompressed_filesize);
 			if (read != entry.uncompressed_filesize) {
 				php_stream_close(sigfile);
+				efree(sig);
 				PHAR_ZIP_FAIL("signature cannot be read");
 			}
-			mydata->sig_flags = PHAR_GET_32(buf);
-			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+			mydata->sig_flags = PHAR_GET_32(sig);
+			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+				efree(sig);
 				if (error) {
 					char *save;
 					php_stream_close(sigfile);
@@ -434,14 +445,9 @@
 				}
 			}
 			php_stream_close(sigfile);
+			efree(sig);
 			/* signature checked out, let's ensure this is the last file in the phar */
-			read = php_stream_read(fp, buf, 4);
-
-			if (read != 4) {
-				PHAR_ZIP_FAIL("corrupted zip file (truncated)");
-			}
-
-			if (!memcmp(buf, "PK\5\6", 4)) {
+			if (i != PHAR_GET_16(locator.count) - 1) {
 				PHAR_ZIP_FAIL("entries exist after signature, invalid phar");
 			}

@@ -1083,15 +1089,18 @@
 		char *signature, sigbuf[8];
 		phar_entry_info entry = {0};
 		php_stream *newfile;
-		off_t tell;
+		off_t tell, st;

 		newfile = php_stream_fopen_tmpfile();
-		tell = php_stream_tell(pass->filefp);
-		/* copy the local files and the zip comment to generate the hash */
+		st = tell = php_stream_tell(pass->filefp);
+		/* copy the local files, central directory, and the zip comment to generate the hash */
 		php_stream_seek(pass->filefp, 0, SEEK_SET);
 		phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL);
+		tell = php_stream_tell(pass->centralfp);
+		php_stream_seek(pass->centralfp, 0, SEEK_SET);
+		phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL);
 		if (metadata->c) {
-			php_stream_write(pass->filefp, metadata->c, metadata->len);
+			php_stream_write(newfile, metadata->c, metadata->len);
 		}

 		if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) {
@@ -1355,6 +1364,9 @@
 	memset(&eocd, 0, sizeof(eocd));

 	strncpy(eocd.signature, "PK\5\6", 4);
+	if (!phar->is_data && !phar->sig_flags) {
+		phar->sig_flags = PHAR_SIG_SHA1;
+	}
 	if (phar->sig_flags) {
 		PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1);
 		PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1);

Modified: php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -62,11 +62,6 @@
 } catch (Exception $e) {
 echo $e->getMessage() . "\n";
 }
-try {
-$data->setSignatureAlgorithm(Phar::MD5);
-} catch (Exception $e) {
-echo $e->getMessage() . "\n";
-}
 $tar = $phar->convertToExecutable(Phar::TAR);
 echo $tar->getPath() . "\n";
 $data = $tar->convertToData();
@@ -188,7 +183,6 @@
 A Phar stub cannot be set in a plain zip archive
 A Phar stub cannot be set in a plain zip archive
 A Phar alias cannot be set in a plain zip archive
-Cannot set signature algorithm, not possible with zip-based phar archives
 %sphar_convert_again2.phar.tar
 %sphar_convert_again2.tar
 %sphar_convert_again2.phar.tar.gz

Modified: php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -46,6 +46,7 @@
 ?>
 ===DONE===
 --CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?>
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?>
 --EXPECT--
 bool(false)

Modified: php/php-src/branches/PHP_5_3/ext/phar/zip.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/phar/zip.c	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/branches/PHP_5_3/ext/phar/zip.c	2009-07-24 19:40:41 UTC (rev 284716)
@@ -350,6 +350,7 @@
 	/* add each central directory item to the manifest */
 	for (i = 0; i < PHAR_GET_16(locator.count); ++i) {
 		phar_zip_central_dir_file zipentry;
+		off_t beforeus = php_stream_tell(fp);

 		if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) {
 			PHAR_ZIP_FAIL("unable to read central directory entry, truncated");
@@ -404,24 +405,34 @@
 		if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
 			size_t read;
 			php_stream *sigfile;
+			off_t now;
+			char *sig;

+			now = php_stream_tell(fp);
 			pefree(entry.filename, entry.is_persistent);
 			sigfile = php_stream_fopen_tmpfile();

 			php_stream_seek(fp, 0, SEEK_SET);
 			/* copy file contents + local headers and zip comment, if any, to be hashed for signature */
 			phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL);
+			/* seek to central directory */
+			php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
+			/* copy central directory header */
+			phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL);
 			if (metadata) {
 				php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len));
 			}
 			php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
-			read = php_stream_read(fp, buf, entry.uncompressed_filesize);
+			sig = (char *) emalloc(entry.uncompressed_filesize);
+			read = php_stream_read(fp, sig, entry.uncompressed_filesize);
 			if (read != entry.uncompressed_filesize) {
 				php_stream_close(sigfile);
+				efree(sig);
 				PHAR_ZIP_FAIL("signature cannot be read");
 			}
-			mydata->sig_flags = PHAR_GET_32(buf);
-			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+			mydata->sig_flags = PHAR_GET_32(sig);
+			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+				efree(sig);
 				if (error) {
 					char *save;
 					php_stream_close(sigfile);
@@ -434,14 +445,9 @@
 				}
 			}
 			php_stream_close(sigfile);
+			efree(sig);
 			/* signature checked out, let's ensure this is the last file in the phar */
-			read = php_stream_read(fp, buf, 4);
-
-			if (read != 4) {
-				PHAR_ZIP_FAIL("corrupted zip file (truncated)");
-			}
-
-			if (!memcmp(buf, "PK\5\6", 4)) {
+			if (i != PHAR_GET_16(locator.count) - 1) {
 				PHAR_ZIP_FAIL("entries exist after signature, invalid phar");
 			}

@@ -1083,15 +1089,18 @@
 		char *signature, sigbuf[8];
 		phar_entry_info entry = {0};
 		php_stream *newfile;
-		off_t tell;
+		off_t tell, st;

 		newfile = php_stream_fopen_tmpfile();
-		tell = php_stream_tell(pass->filefp);
-		/* copy the local files and the zip comment to generate the hash */
+		st = tell = php_stream_tell(pass->filefp);
+		/* copy the local files, central directory, and the zip comment to generate the hash */
 		php_stream_seek(pass->filefp, 0, SEEK_SET);
 		phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL);
+		tell = php_stream_tell(pass->centralfp);
+		php_stream_seek(pass->centralfp, 0, SEEK_SET);
+		phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL);
 		if (metadata->c) {
-			php_stream_write(pass->filefp, metadata->c, metadata->len);
+			php_stream_write(newfile, metadata->c, metadata->len);
 		}

 		if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) {
@@ -1355,6 +1364,9 @@
 	memset(&eocd, 0, sizeof(eocd));

 	strncpy(eocd.signature, "PK\5\6", 4);
+	if (!phar->is_data && !phar->sig_flags) {
+		phar->sig_flags = PHAR_SIG_SHA1;
+	}
 	if (phar->sig_flags) {
 		PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1);
 		PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1);

Modified: php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt
===================================================================
--- php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -62,11 +62,6 @@
 } catch (Exception $e) {
 echo $e->getMessage() . "\n";
 }
-try {
-$data->setSignatureAlgorithm(Phar::MD5);
-} catch (Exception $e) {
-echo $e->getMessage() . "\n";
-}
 $tar = $phar->convertToExecutable(Phar::TAR);
 echo $tar->getPath() . "\n";
 $data = $tar->convertToData();
@@ -188,7 +183,6 @@
 A Phar stub cannot be set in a plain zip archive
 A Phar stub cannot be set in a plain zip archive
 A Phar alias cannot be set in a plain zip archive
-Cannot set signature algorithm, not possible with zip-based phar archives
 %sphar_convert_again2.phar.tar
 %sphar_convert_again2.tar
 %sphar_convert_again2.phar.tar.gz

Modified: php/php-src/trunk/ext/phar/tests/zip/all.phpt
===================================================================
--- php/php-src/trunk/ext/phar/tests/zip/all.phpt	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/trunk/ext/phar/tests/zip/all.phpt	2009-07-24 19:40:41 UTC (rev 284716)
@@ -46,6 +46,7 @@
 ?>
 ===DONE===
 --CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?>
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?>
 --EXPECT--
 bool(false)

Modified: php/php-src/trunk/ext/phar/zip.c
===================================================================
--- php/php-src/trunk/ext/phar/zip.c	2009-07-24 19:21:10 UTC (rev 284715)
+++ php/php-src/trunk/ext/phar/zip.c	2009-07-24 19:40:41 UTC (rev 284716)
@@ -350,6 +350,7 @@
 	/* add each central directory item to the manifest */
 	for (i = 0; i < PHAR_GET_16(locator.count); ++i) {
 		phar_zip_central_dir_file zipentry;
+		off_t beforeus = php_stream_tell(fp);

 		if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) {
 			PHAR_ZIP_FAIL("unable to read central directory entry, truncated");
@@ -404,24 +405,34 @@
 		if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
 			size_t read;
 			php_stream *sigfile;
+			off_t now;
+			char *sig;

+			now = php_stream_tell(fp);
 			pefree(entry.filename, entry.is_persistent);
 			sigfile = php_stream_fopen_tmpfile();

 			php_stream_seek(fp, 0, SEEK_SET);
 			/* copy file contents + local headers and zip comment, if any, to be hashed for signature */
 			phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL);
+			/* seek to central directory */
+			php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
+			/* copy central directory header */
+			phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL);
 			if (metadata) {
 				php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len));
 			}
 			php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
-			read = php_stream_read(fp, buf, entry.uncompressed_filesize);
+			sig = (char *) emalloc(entry.uncompressed_filesize);
+			read = php_stream_read(fp, sig, entry.uncompressed_filesize);
 			if (read != entry.uncompressed_filesize) {
 				php_stream_close(sigfile);
+				efree(sig);
 				PHAR_ZIP_FAIL("signature cannot be read");
 			}
-			mydata->sig_flags = PHAR_GET_32(buf);
-			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+			mydata->sig_flags = PHAR_GET_32(sig);
+			if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
+				efree(sig);
 				if (error) {
 					char *save;
 					php_stream_close(sigfile);
@@ -434,14 +445,9 @@
 				}
 			}
 			php_stream_close(sigfile);
+			efree(sig);
 			/* signature checked out, let's ensure this is the last file in the phar */
-			read = php_stream_read(fp, buf, 4);
-
-			if (read != 4) {
-				PHAR_ZIP_FAIL("corrupted zip file (truncated)");
-			}
-
-			if (!memcmp(buf, "PK\5\6", 4)) {
+			if (i != PHAR_GET_16(locator.count) - 1) {
 				PHAR_ZIP_FAIL("entries exist after signature, invalid phar");
 			}

@@ -1083,15 +1089,18 @@
 		char *signature, sigbuf[8];
 		phar_entry_info entry = {0};
 		php_stream *newfile;
-		off_t tell;
+		off_t tell, st;

 		newfile = php_stream_fopen_tmpfile();
-		tell = php_stream_tell(pass->filefp);
-		/* copy the local files and the zip comment to generate the hash */
+		st = tell = php_stream_tell(pass->filefp);
+		/* copy the local files, central directory, and the zip comment to generate the hash */
 		php_stream_seek(pass->filefp, 0, SEEK_SET);
 		phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL);
+		tell = php_stream_tell(pass->centralfp);
+		php_stream_seek(pass->centralfp, 0, SEEK_SET);
+		phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL);
 		if (metadata->c) {
-			php_stream_write(pass->filefp, metadata->c, metadata->len);
+			php_stream_write(newfile, metadata->c, metadata->len);
 		}

 		if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) {
@@ -1355,6 +1364,9 @@
 	memset(&eocd, 0, sizeof(eocd));

 	strncpy(eocd.signature, "PK\5\6", 4);
+	if (!phar->is_data && !phar->sig_flags) {
+		phar->sig_flags = PHAR_SIG_SHA1;
+	}
 	if (phar->sig_flags) {
 		PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1);
 		PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1);
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to