[pacman-dev] [PATCH] util: fix line length calc in _alpm_archive_fgets
Allan McRae
allan at archlinux.org
Thu Jul 19 20:44:48 EDT 2012
On 20/07/12 00:54, Dave Reisner wrote:
> 74274b5dc347ba70 which added the real_line_size to the buffer struct
> didn't properly account for what happens when archive_fgets has to loop
> more than once to find the end of a line. In most cases, this isn't a
> problem, but could potentially cause a longer line such as PGP signature
> to be improperly read.
>
> This patch fixes the oversight and focuses on only calculating the line
> length when we hit the end of line marker. The effective length is then
> calculated via pointer arithmetic as:
>
> (start_of_last_read + read_length) - start_of_line
>
> Signed-off-by: Dave Reisner <dreisner at archlinux.org>
> ---
> Allan noticed that PHP was reporting an invalid sig and bisected it back to me,
> (of course). This was lucky enough to only affect about .1% of the sync DB, and
> mostly the PGPSIG field, naturally due to it being the largest field in the DB
> by a wide margin.
>
> lib/libalpm/util.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
> index c2b5d44..721125a 100644
> --- a/lib/libalpm/util.c
> +++ b/lib/libalpm/util.c
> @@ -1011,15 +1011,16 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
> }
>
> if(eol) {
> - size_t len = b->real_line_size = (size_t)(eol - b->block_offset);
> + size_t len = (size_t)(eol - b->block_offset);
> memcpy(b->line_offset, b->block_offset, len);
> b->line_offset[len] = '\0';
> b->block_offset = eol + 1;
> + b->real_line_size = b->line_offset + len - b->line;
> /* this is the main return point; from here you can read b->line */
> return ARCHIVE_OK;
> } else {
> /* we've looked through the whole block but no newline, copy it */
> - size_t len = b->real_line_size = (size_t)(b->block + b->block_size - b->block_offset);
> + size_t len = (size_t)(b->block + b->block_size - b->block_offset);
> memcpy(b->line_offset, b->block_offset, len);
> b->line_offset += len;
> b->block_offset = b->block + b->block_size;
Just for the record... here is my version which does not break pactests:
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 0db9e87..e91460e 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -947,6 +947,7 @@ int _alpm_archive_fgets(struct archive *a, struct
archive_read_buffer *b)
{
/* ensure we start populating our line buffer at the beginning */
b->line_offset = b->line;
+ b->real_line_size = 0;
while(1) {
size_t block_remaining;
@@ -1008,7 +1009,8 @@ int _alpm_archive_fgets(struct archive *a, struct
archive_read_buffer *b)
}
if(eol) {
- size_t len = b->real_line_size = (size_t)(eol - b->block_offset);
+ size_t len = (size_t)(eol - b->block_offset);
+ b->real_line_size += len;
memcpy(b->line_offset, b->block_offset, len);
b->line_offset[len] = '\0';
b->block_offset = eol + 1;
@@ -1016,7 +1018,8 @@ int _alpm_archive_fgets(struct archive *a, struct
archive_read_buffer *b)
return ARCHIVE_OK;
} else {
/* we've looked through the whole block but no newline, copy it */
- size_t len = b->real_line_size = (size_t)(b->block + b->block_size -
b->block_offset);
+ size_t len = (size_t)(b->block + b->block_size - b->block_offset);
+ b->real_line_size += len;
memcpy(b->line_offset, b->block_offset, len);
b->line_offset += len;
b->block_offset = b->block + b->block_size;
More information about the pacman-dev
mailing list