1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include "test.h" 26 27 DEFINE_TEST(test_read_pax_truncated) 28 { 29 struct archive_entry *ae; 30 struct archive *a; 31 size_t used, i, buff_size = 1000000; 32 size_t filedata_size = 100000; 33 char *buff = malloc(buff_size); 34 char *buff2 = malloc(buff_size); 35 char *filedata = malloc(filedata_size); 36 37 /* Create a new archive in memory. */ 38 assert((a = archive_write_new()) != NULL); 39 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_pax(a)); 40 assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); 41 assertEqualIntA(a, ARCHIVE_OK, 42 archive_write_open_memory(a, buff, buff_size, &used)); 43 44 /* 45 * Write a file to it. 46 */ 47 assert((ae = archive_entry_new()) != NULL); 48 archive_entry_copy_pathname(ae, "file"); 49 archive_entry_set_mode(ae, S_IFREG | 0755); 50 fill_with_pseudorandom_data(filedata, filedata_size); 51 52 archive_entry_set_atime(ae, 1, 2); 53 archive_entry_set_ctime(ae, 3, 4); 54 archive_entry_set_mtime(ae, 5, 6); 55 archive_entry_set_size(ae, filedata_size); 56 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 57 archive_entry_free(ae); 58 assertEqualIntA(a, (int)filedata_size, 59 (int)archive_write_data(a, filedata, filedata_size)); 60 61 /* Close out the archive. */ 62 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 63 assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 64 65 /* Now, read back a truncated version of the archive and 66 * verify that we get an appropriate error. */ 67 for (i = 1; i < used + 100; i += 100) { 68 assert((a = archive_read_new()) != NULL); 69 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 70 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 71 /* If it's truncated very early, the file type detection should fail. */ 72 if (i < 512) { 73 assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory_minimal(a, buff, i, 13)); 74 goto wrap_up; 75 } else { 76 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, buff, i, 13)); 77 } 78 79 /* If it's truncated in a header, the header read should fail. */ 80 if (i < 1536) { 81 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); 82 goto wrap_up; 83 } else { 84 failure("Archive truncated to %zu bytes", i); 85 assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 86 } 87 88 /* If it's truncated in the body, the body read should fail. */ 89 if (i < 1536 + filedata_size) { 90 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, filedata, filedata_size)); 91 goto wrap_up; 92 } else { 93 failure("Archive truncated to %zu bytes", i); 94 assertEqualIntA(a, filedata_size, 95 archive_read_data(a, filedata, filedata_size)); 96 } 97 98 /* Verify the end of the archive. */ 99 /* Archive must be long enough to capture a 512-byte 100 * block of zeroes after the entry. (POSIX requires a 101 * second block of zeros to be written but libarchive 102 * does not return an error if it can't consume 103 * it.) */ 104 if (i < 1536 + 512*((filedata_size + 511)/512) + 512) { 105 failure("i=%zu minsize=%zu", i, 106 1536 + 512*((filedata_size + 511)/512) + 512); 107 assertEqualIntA(a, ARCHIVE_FATAL, 108 archive_read_next_header(a, &ae)); 109 } else { 110 assertEqualIntA(a, ARCHIVE_EOF, 111 archive_read_next_header(a, &ae)); 112 } 113 wrap_up: 114 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 115 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 116 } 117 118 119 120 /* Same as above, except skip the body instead of reading it. */ 121 for (i = 1; i < used + 100; i += 100) { 122 assert((a = archive_read_new()) != NULL); 123 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 124 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 125 /* If it's truncated very early, file type detection should fail. */ 126 if (i < 512) { 127 assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, buff, i, 7)); 128 goto wrap_up2; 129 } else { 130 assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, buff, i, 7)); 131 } 132 133 if (i < 1536) { 134 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); 135 goto wrap_up2; 136 } else { 137 assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 138 } 139 140 if (i < 1536 + 512*((filedata_size+511)/512)) { 141 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data_skip(a)); 142 goto wrap_up2; 143 } else { 144 assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); 145 } 146 147 /* Verify the end of the archive. */ 148 /* Archive must be long enough to capture a 512-byte 149 * block of zeroes after the entry. (POSIX requires a 150 * second block of zeros to be written but libarchive 151 * does not return an error if it can't consume 152 * it.) */ 153 if (i < 1536 + 512*((filedata_size + 511)/512) + 512) { 154 assertEqualIntA(a, ARCHIVE_FATAL, 155 archive_read_next_header(a, &ae)); 156 } else { 157 assertEqualIntA(a, ARCHIVE_EOF, 158 archive_read_next_header(a, &ae)); 159 } 160 wrap_up2: 161 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 162 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 163 } 164 165 /* Now, damage the archive in various ways and test the responses. */ 166 167 /* Damage the first size field in the pax attributes. */ 168 memcpy(buff2, buff, buff_size); 169 buff2[512] = '9'; 170 buff2[513] = '9'; 171 buff2[514] = 'A'; /* Non-digit in size. */ 172 assert((a = archive_read_new()) != NULL); 173 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 174 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 175 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 176 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 177 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 178 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 179 180 /* Damage the size field in the pax attributes. */ 181 memcpy(buff2, buff, buff_size); 182 buff2[512] = 'A'; /* First character not a digit. */ 183 assert((a = archive_read_new()) != NULL); 184 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 185 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 186 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 187 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 188 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 189 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 190 191 /* Damage the size field in the pax attributes. */ 192 memcpy(buff2, buff, buff_size); 193 for (i = 512; i < 520; i++) /* Size over 999999. */ 194 buff2[i] = '9'; 195 buff2[i] = ' '; 196 assert((a = archive_read_new()) != NULL); 197 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 198 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 199 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 200 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 201 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 202 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 203 204 /* Damage the size field in the pax attributes. */ 205 memcpy(buff2, buff, buff_size); 206 buff2[512] = '9'; /* Valid format, but larger than attribute area. */ 207 buff2[513] = '9'; 208 buff2[514] = '9'; 209 buff2[515] = ' '; 210 assert((a = archive_read_new()) != NULL); 211 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 212 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 213 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 214 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 215 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 216 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 217 218 /* Damage the size field in the pax attributes. */ 219 memcpy(buff2, buff, buff_size); 220 buff2[512] = '1'; /* Too small. */ 221 buff2[513] = ' '; 222 assert((a = archive_read_new()) != NULL); 223 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 224 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 225 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 226 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 227 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 228 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 229 230 /* Damage the size field in the pax attributes. */ 231 memcpy(buff2, buff, buff_size); 232 buff2[512] = ' '; /* No size given. */ 233 assert((a = archive_read_new()) != NULL); 234 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 235 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 236 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 237 assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); 238 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 239 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 240 241 /* Damage the ustar header. */ 242 memcpy(buff2, buff, buff_size); 243 buff2[1024]++; /* Break the checksum. */ 244 assert((a = archive_read_new()) != NULL); 245 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 246 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 247 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff2, used)); 248 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); 249 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 250 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 251 252 /* 253 * TODO: Damage the ustar header in various ways and fixup the 254 * checksum in order to test boundary cases in the innermost 255 * ustar header parsing. 256 */ 257 258 free(buff); 259 free(buff2); 260 free(filedata); 261 } 262