From 7db09c854365c704250203db691f9aa263038f23 Mon Sep 17 00:00:00 2001 From: xarkes Date: Thu, 24 Aug 2017 13:37:20 +0200 Subject: [PATCH] Ar fixes (#8292) --- shlr/ar/ar.c | 98 ++++++++++++++++++++++------------------------------ shlr/ar/ar.h | 2 +- 2 files changed, 43 insertions(+), 57 deletions(-) diff --git a/shlr/ar/ar.c b/shlr/ar/ar.c index 1f03cd7638..47b49f0ac6 100644 --- a/shlr/ar/ar.c +++ b/shlr/ar/ar.c @@ -7,6 +7,7 @@ const char *AR_MAGIC_HEADER = "!\n"; const char *AR_FILE_HEADER_END = "`\n"; +const int AR_FILENAME_LEN = 16; /* Used to lookup filename table */ static int index_filename = -2; @@ -34,25 +35,17 @@ R_API RBuffer *ar_open_file(const char *arname, const char *filename) { } files = r_list_new (); /* Parse archive */ - ar_read_file (b, buffer, BUF_SIZE, true, NULL, NULL); + ar_read_file (b, buffer, true, NULL, NULL); ar_read_filename_table (b, buffer, files, filename); /* If b->base is set, then we found the file root in the archive */ while (r && !b->base) { - ar_read (b, buffer, 2); - /* Fix padding */ - if (*buffer == '\n') { - buffer[0] = buffer[1]; - b->cur -= 1; - ar_read (b, buffer, 2); - } - r = ar_read_file (b, buffer, BUF_SIZE, false, files, filename); + r = ar_read_file (b, buffer, false, files, filename); } if (!filename) { RListIter *iter; char *name; - puts ("Available files:\n"); r_list_foreach (files, iter, name) { printf ("%s\n", name); } @@ -121,7 +114,7 @@ int ar_read_header(RBuffer *b, char *buffer) { return r; } -int ar_read_file(RBuffer *b, char *buffer, int bufsz, bool lookup, RList *files, const char *filename) { +int ar_read_file(RBuffer *b, char *buffer, bool lookup, RList *files, const char *filename) { ut64 filesize = 0; char *tmp = NULL; char *curfile = NULL; @@ -130,26 +123,35 @@ int ar_read_file(RBuffer *b, char *buffer, int bufsz, bool lookup, RList *files, /* File identifier */ if (lookup) { - r = ar_read (b, buffer, bufsz); + ar_read (b, buffer, AR_FILENAME_LEN); } else { - r = ar_read (b, buffer + 2, bufsz - 1); + ar_read (b, buffer, 2); + /* Fix padding issues */ + if (*buffer == '\n') { + buffer[0] = buffer[1]; + b->cur--; + ar_read (b, buffer, 2); + } + ar_read (b, buffer + 2, AR_FILENAME_LEN - 2); } - buffer[bufsz] = 0; + buffer[AR_FILENAME_LEN] = '\0'; /* Fix some padding issues */ - if (buffer[15] != '/' && buffer[15] != ' ') { + if (buffer[AR_FILENAME_LEN - 1] != '/' && buffer[AR_FILENAME_LEN - 1] != ' ') { + // Find padding offset tmp = (char *)r_str_lchr (buffer, ' '); if (!tmp) { - return 0; + goto fail; } int dif = (int) (tmp - buffer); dif = 31 - dif; + // Re-read the whole filename b->cur -= dif; - r = ar_read (b, buffer, 16); + r = ar_read (b, buffer, AR_FILENAME_LEN); } free (curfile); curfile = strdup (buffer); if (!curfile) { - return 0; + goto fail; } /* If /XX then refer to filename table later */ if (curfile[0] == '/' && curfile[1] >= '0' && curfile[1] <= '9') { @@ -158,49 +160,29 @@ int ar_read_file(RBuffer *b, char *buffer, int bufsz, bool lookup, RList *files, /* Read filename */ tmp = strchr (curfile, '/'); if (!tmp) { - return 0; + goto fail; } *tmp = '\0'; if (files) { r_list_append (files, strdup (curfile)); } } - /* File timestamp */ - r = ar_read (b, buffer, 12); - if (r != 12) { - free (curfile); - return 0; - } - /* Owner id */ - r = ar_read (b, buffer, 6); - if (r != 6) { - free (curfile); - return 0; - } - /* Group id */ - r = ar_read (b, buffer, 6); - if (r != 6) { - free (curfile); - return 0; - } - /* File mode */ - r = ar_read (b, buffer, 8); - if (r != 8) { - free (curfile); - return 0; - } - /* File size */ - r = ar_read (b, buffer, 10); - filesize = strtoull (buffer, &tmp, 10); - if (r != 10) { - free (curfile); - return 0; + /* Timestamp 12 + * Owner ID 6 + * Group ID 6 + * File Mode 8 + * File Size 10 + * Header end 2 */ + r = ar_read (b, buffer, 44); + if (r != 44) { + goto fail; } + + filesize = strtoull (buffer + 32, &tmp, 10); + /* Header end */ - r = ar_read (b, buffer, 2); - if (strncmp (buffer, AR_FILE_HEADER_END, 2)) { - free (curfile); - return 0; + if (strncmp (buffer + 42, AR_FILE_HEADER_END, 2)) { + goto fail; } /* File content */ @@ -218,15 +200,19 @@ int ar_read_file(RBuffer *b, char *buffer, int bufsz, bool lookup, RList *files, b->cur += filesize - 1; free (curfile); return filesize; +fail: + free (curfile); + return 0; } int ar_read_filename_table(RBuffer *b, char *buffer, RList *files, const char *filename) { - int r = ar_read (b, buffer, 16); - if (r != 16) { + int r = ar_read (b, buffer, AR_FILENAME_LEN); + if (r != AR_FILENAME_LEN) { return 0; } if (strncmp (buffer, "//", 2)) { - b->cur -= 16; + // What we read was not a filename table, just go back + b->cur -= AR_FILENAME_LEN; return 0; } diff --git a/shlr/ar/ar.h b/shlr/ar/ar.h index 9c2803f896..6f4f2067c3 100644 --- a/shlr/ar/ar.h +++ b/shlr/ar/ar.h @@ -12,6 +12,6 @@ R_API int ar_write_at(RBuffer *b, ut64 off, void *buf, int count); int ar_read(RBuffer *b, void *dest, int len); int ar_read_until_slash(RBuffer *b, char *buffer, int limit); int ar_read_header(RBuffer *b, char *buffer); -int ar_read_file(RBuffer *b, char *buffer, int bufsz, bool lookup, RList *files, const char *filename); +int ar_read_file(RBuffer *b, char *buffer, bool lookup, RList *files, const char *filename); int ar_read_filename_table(RBuffer *b, char *buffer, RList *files, const char *filename); #endif // _AR_H