]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Issue 247:Unicode filenames inside RAR not working.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 6 Mar 2012 09:55:18 +0000 (18:55 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Wed, 7 Mar 2012 10:20:31 +0000 (19:20 +0900)
libarchive/archive_read_support_format_rar.c
libarchive/test/test_read_format_rar.c
libarchive/test/test_read_format_rar_unicode.rar.uu

index d2a893ec5bba0b39cb958c2e53ef0d542ad3d03e..4b53b13ddbb4b8e15c487defc71d96c71ddf372c 100644 (file)
@@ -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);
index 8a73a78e5a09bc860c7020c5534d69b05016ba2c..a7c61f9c3ec1d2398c4812b2163d6cef40ebfccb 100644 (file)
@@ -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));
 }
index cfe6e40d51f3ca56371fb8996eb3f05c1d9b4e58..8469e995bc381f1e2532594ad6d555382f32277f 100644 (file)
@@ -11,7 +11,8 @@ M5H*U@J*#=(-(@XN#7P"(:&A@,(@P7*JP95<P1##5,*BI,.LPP#``\"8YA&UX
 M=."2,P````````````(`````#VGA/A0P#@`0````E5R"OH+F`(AH:&`PB#``
 M\.H)?ED.="""2``V````-@````,E@OM=6%0+/Q0P*`#MH0``Z*&HXX&@XX*(
 M7..#E>."H>."I..#JP"(:&A@,(@P7*K5,*$PI##K,.:\HN6ME^F5M^.!A..#
-ME>."H>."I..#J^60C6QO;F<M9FEL96YA;64M:6XMYKRBY:V7+G1X=,0]>P!`
-"!P``
+ME>."H>."I..#J^60C6QO;F<M9FEL96YA;64M:6XMYKRBY:V7+G1X=)MJ=""`
+M0``/````$`````,%T+85W81G0!TS(`"T@0``86)C9&5F9VAI:FML;6YO<'%R
+D<^.#AN."N>.#B"YT>'0`D/\0?^2Y_">#,#TN'-+$/7L`0`<`
 `
 end