X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fxheader.c;h=0cb5bb21957b94c08c6950b7cf921b329a7f22ac;hb=29c902bc4949f6020df6470aa1115ce15dab802a;hp=1ad6be80ecda2786ef9728d5d797e6cc173411cc;hpb=7347b4f5d51c15bb19637ea52e9bf7dff832cc52;p=chaz%2Ftar diff --git a/src/xheader.c b/src/xheader.c index 1ad6be8..0cb5bb2 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -1,6 +1,6 @@ /* POSIX extended headers for tar. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -26,10 +26,6 @@ #include "common.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -#include - #include static bool xheader_protected_pattern_p (char const *pattern); @@ -163,7 +159,7 @@ xheader_set_keyword_equal (char *kw, char *eq) if (strcmp (kw, "delete") == 0) { if (xheader_protected_pattern_p (p)) - USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), p)); + USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p))); xheader_list_append (&keyword_pattern_list, p, NULL); } else if (strcmp (kw, "exthdr.name") == 0) @@ -467,51 +463,70 @@ xheader_protected_keyword_p (const char *keyword) return false; } -/* Decodes a single extended header record. Advances P to the next - record. - Returns true on success, false otherwise. */ +/* Decode a single extended header record, advancing *PTR to the next record. + Return true on success, false otherwise. */ static bool -decode_record (char **p, +decode_record (char **ptr, void (*handler) (void *, char const *, char const *), void *data) { - size_t len; + char *start = *ptr; + char *p = start; + unsigned long int len; + char *len_lim; char const *keyword; - char *start = *p; - char endc; + char *nextp; + size_t len_max = extended_header.buffer + extended_header.size - start; - if (**p == 0) - return false; + while (*p == ' ' || *p == '\t') + p++; - len = strtoul (*p, p, 10); - if (**p != ' ') + if (! ISDIGIT (*p)) { - ERROR ((0, 0, - _("Malformed extended header: missing whitespace after the length"))); + if (*p) + ERROR ((0, 0, _("Malformed extended header: missing length"))); return false; } - keyword = ++*p; - for (;*p < start + len; ++*p) - if (**p == '=') - break; + errno = 0; + len = strtoul (p, &len_lim, 10); - if (**p != '=') + if (len_max < len || (len == ULONG_MAX && errno == ERANGE)) { - ERROR ((0, 0, _("Malformed extended header: missing equal sign"))); + ERROR ((0, 0, _("Malformed extended header: length out of range"))); return false; } - **p = 0; + nextp = start + len; - endc = start[len-1]; - start[len-1] = 0; + for (p = len_lim; *p == ' ' || *p == '\t'; p++) + continue; + if (p == len_lim) + { + ERROR ((0, 0, + _("Malformed extended header: missing blank after length"))); + return false; + } + + keyword = p; + p = strchr (p, '='); + if (! (p && p < nextp)) + { + ERROR ((0, 0, _("Malformed extended header: missing equal sign"))); + return false; + } - handler (data, keyword, *p + 1); + if (nextp[-1] != '\n') + { + ERROR ((0, 0, _("Malformed extended header: missing newline"))); + return false; + } - start[len-1] = endc; - **p = '='; - *p = &start[len]; + *p = nextp[-1] = '\0'; + handler (data, keyword, p + 1); + *p = '='; + nextp[-1] = '\n'; + *ptr = nextp; return true; } @@ -550,11 +565,8 @@ xheader_decode (struct tar_stat_info *st) if (extended_header.size) { char *p = extended_header.buffer + BLOCKSIZE; - char *endp = &extended_header.buffer[extended_header.size-1]; - - while (p < endp) - if (!decode_record (&p, decx, st)) - break; + while (decode_record (&p, decx, st)) + continue; } run_override_list (keyword_override_list, st); } @@ -572,12 +584,10 @@ xheader_decode_global (void) if (extended_header.size) { char *p = extended_header.buffer + BLOCKSIZE; - char *endp = &extended_header.buffer[extended_header.size-1]; xheader_list_destroy (&global_header_override_list); - while (p < endp) - if (!decode_record (&p, decg, &global_header_override_list)) - break; + while (decode_record (&p, decg, &global_header_override_list)) + continue; } } @@ -619,6 +629,7 @@ xheader_read (union block *p, size_t size) extended_header.size = size; nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE; extended_header.buffer = xmalloc (size + 1); + extended_header.buffer[size] = '\0'; do {