diff options
author | Dan McGee <dan@archlinux.org> | 2011-06-23 01:17:38 +0200 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2011-06-24 21:03:51 +0200 |
commit | 719e0d3ddb300a8f0f8367b516c0e3c9579c4448 (patch) | |
tree | e415dccd96bb55269d102b84f6d8403f37c86811 | |
parent | 1187edb38c5ba42d27fd1de8e97aab658049367f (diff) | |
download | pacman-719e0d3ddb300a8f0f8367b516c0e3c9579c4448.tar.gz pacman-719e0d3ddb300a8f0f8367b516c0e3c9579c4448.tar.xz |
archive_fgets(): ensure we return any trailing text with no newline
Discovered this when doing some pactest rewrite work to generate
archives in memory only. If a sync database file or PKGINFO file is
missing a newline on the final line, the text from that line gets tossed
aside and never read into the package struct. This is pretty critical
when that last line is a depend or something.
Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r-- | lib/libalpm/util.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 4976703a..9f6a5acd 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -760,9 +760,8 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) &b->block_size, &offset); b->block_offset = b->block; - /* error or end of archive with no data read, cleanup */ - if(b->ret < ARCHIVE_OK || - (b->block_size == 0 && b->ret == ARCHIVE_EOF)) { + /* error, cleanup */ + if(b->ret < ARCHIVE_OK) { goto cleanup; } } @@ -779,19 +778,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) /* allocate our buffer, or ensure our existing one is big enough */ if(!b->line) { /* set the initial buffer to the read block_size */ - CALLOC(b->line, b->block_size + 1, sizeof(char), return ENOMEM); + CALLOC(b->line, b->block_size + 1, sizeof(char), b->ret = -ENOMEM; goto cleanup); b->line_size = b->block_size + 1; b->line_offset = b->line; } else { size_t needed = (size_t)((b->line_offset - b->line) + (i - b->block_offset) + 1); if(needed > b->max_line_size) { - return ERANGE; + b->ret = -ERANGE; + goto cleanup; } if(needed > b->line_size) { /* need to realloc + copy data to fit total length */ char *new; - CALLOC(new, needed, sizeof(char), return ENOMEM); + CALLOC(new, needed, sizeof(char), b->ret = -ENOMEM; goto cleanup); memcpy(new, b->line, b->line_size); b->line_size = needed; b->line_offset = new + (b->line_offset - b->line); @@ -813,6 +813,12 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) memcpy(b->line_offset, b->block_offset, len); b->line_offset += len; b->block_offset = i; + /* there was no new data, return what is left; saved ARCHIVE_EOF will be + * returned on next call */ + if(len == 0) { + b->line_offset[0] = '\0'; + return ARCHIVE_OK; + } } } |