From: Michihiro NAKAJIMA Date: Tue, 6 Mar 2012 09:55:18 +0000 (+0900) Subject: Issue 247:Unicode filenames inside RAR not working. X-Git-Tag: v3.0.4~43 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=248ca692681fcd211e504d1b3fe4816f5f0e4e13;p=thirdparty%2Flibarchive.git Issue 247:Unicode filenames inside RAR not working. --- diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index d2a893ec5..4b53b13dd 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -1161,8 +1161,8 @@ read_header(struct archive_read *a, struct archive_entry *entry, "Invalid filename size"); return (ARCHIVE_FATAL); } - if (rar->filename_allocated < filename_size+2) { - rar->filename = realloc(rar->filename, filename_size+2); + if (rar->filename_allocated < filename_size * 2 + 2) { + rar->filename = realloc(rar->filename, filename_size * 2 + 2); if (rar->filename == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); @@ -1176,15 +1176,17 @@ read_header(struct archive_read *a, struct archive_entry *entry, { if (filename_size != strlen(filename)) { - unsigned char highbyte, flagbits, flagbyte, length, offset; + unsigned char highbyte, flagbits, flagbyte, offset; + unsigned fn_end; end = filename_size; + fn_end = filename_size * 2; filename_size = 0; offset = strlen(filename) + 1; highbyte = *(p + offset++); flagbits = 0; flagbyte = 0; - while (offset < end && filename_size < end) + while (offset < end && filename_size < fn_end) { if (!flagbits) { @@ -1210,19 +1212,26 @@ read_header(struct archive_read *a, struct archive_entry *entry, break; case 3: { - length = *(p + offset++); - while (length) - { - if (filename_size >= end) - break; - filename[filename_size++] = *(p + offset); + char extra, high; + uint8_t length = *(p + offset++); + + if (length & 0x80) { + extra = *(p + offset++); + high = (char)highbyte; + } else + extra = high = 0; + length = (length & 0x7f) + 2; + while (length && filename_size < fn_end) { + unsigned cp = filename_size >> 1; + filename[filename_size++] = high; + filename[filename_size++] = p[cp] + extra; length--; } } break; } } - if (filename_size >= end) { + if (filename_size > fn_end) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid filename"); return (ARCHIVE_FATAL); diff --git a/libarchive/test/test_read_format_rar.c b/libarchive/test/test_read_format_rar.c index 8a73a78e5..a7c61f9c3 100644 --- a/libarchive/test/test_read_format_rar.c +++ b/libarchive/test/test_read_format_rar.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2011 Andres Mejia + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -278,9 +279,19 @@ test_unicode_UTF8(void) assertEqualInt(41453, archive_entry_mode(ae)); assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + /* Sixth header */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualUTF8String( + "abcdefghijklmnopqrs\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33204, archive_entry_mode(ae)); + assertEqualIntA(a, 16, archive_read_data(a, buff, sizeof(buff))); + /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); - assertEqualInt(5, archive_file_count(a)); + assertEqualInt(6, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -364,9 +375,19 @@ test_unicode_CP932(void) assertEqualInt(41453, archive_entry_mode(ae)); assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); + /* Sixth header */ + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualUTF8String( + "abcdefghijklmnopqrs\x83\x65\x83\x58\x83\x67.txt", + archive_entry_pathname(ae)); + assertA((int)archive_entry_mtime(ae)); + assertEqualInt(16, archive_entry_size(ae)); + assertEqualInt(33204, archive_entry_mode(ae)); + assertEqualIntA(a, 16, archive_read_data(a, buff, sizeof(buff))); + /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); - assertEqualInt(5, archive_file_count(a)); + assertEqualInt(6, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_unicode.rar.uu b/libarchive/test/test_read_format_rar_unicode.rar.uu index cfe6e40d5..8469e995b 100644 --- a/libarchive/test/test_read_format_rar_unicode.rar.uu +++ b/libarchive/test/test_read_format_rar_unicode.rar.uu @@ -11,7 +11,8 @@ M5H*U@J*#=(-(@XN#7P"(:&A@,(@P7*JP95."H>."I..#JP"(:&A@,(@P7*K5,*$PI##K,.:\HN6ME^F5M^.!A..# -ME>."H>."I..#J^60C6QO;FP!` -"!P`` +ME>."H>."I..#J^60C6QO;F.#B"YT>'0`D/\0?^2Y_">#,#TN'-+$/7L`0`<` ` end