diff --git a/src/gufi_vt.c b/src/gufi_vt.c index 705ee66e0..920bd6334 100644 --- a/src/gufi_vt.c +++ b/src/gufi_vt.c @@ -205,45 +205,37 @@ static const size_t TL = sizeof(char) + sizeof(size_t); /* read TLV rows terminated by newline - this only works because type is in the range [1, 5] */ static int gufi_query_read_row(gufi_vtab_cursor *pCur) { - size_t size = sizeof(int); - char *buf = malloc(size); + static const size_t row_prefix = sizeof(size_t) + sizeof(int); + char *buf = NULL; char *curr = buf; - ptrdiff_t curr_offset = 0; size_t *starts = NULL; /* index of where each column starts in buf */ - int count = 0; /* number of columns */ + size_t row_len = 0; + int count = 0; - // each row is prefixed with a count - if (fread(curr, sizeof(char), sizeof(int), pCur->output) != sizeof(int)) { + /* row length */ + if (fread(&row_len, sizeof(char), sizeof(row_len), pCur->output) != sizeof(row_len)) { + if (ferror(pCur->output)) { + fprintf(stderr, "Error: Could not read row length\n"); + } goto error; } - count = * (int *) curr; - starts = malloc(count * sizeof(size_t)); + /* column count */ + if (fread(&count, sizeof(char), sizeof(count), pCur->output) != sizeof(count)) { + fprintf(stderr, "Error: Could not read column count\n"); + goto error; + } - curr += sizeof(int); + /* buf does not contain row prefix */ + buf = malloc(row_len - row_prefix); + curr = buf; + starts = malloc(count * sizeof(size_t)); - char *new_buf = NULL; for(int i = 0; i < count; i++) { + /* column start points to type */ starts[i] = curr - buf; - /* add space for type and length */ - size += TL; - - curr_offset = curr - buf; - - /* reallocate buffer for type and length */ - new_buf = realloc(buf, size); - if (!new_buf) { - const int err = errno; - fprintf(stderr, "Error: Could not resize buffer for reading column type and length. New size: %zu: %s (%d)\n", - size, strerror(err), err); - goto error; - } - - buf = new_buf; - curr = buf + curr_offset; - /* read type and length */ const size_t tl = fread(curr, sizeof(char), TL, pCur->output); if (tl != TL) { @@ -253,26 +245,11 @@ static int gufi_query_read_row(gufi_vtab_cursor *pCur) { const size_t value_len = * (size_t *) (curr + sizeof(char)); - size += value_len; /* update buffer size with value length */ - curr += TL; /* to go to end of buffer/start of value */ - - curr_offset = curr - buf; - - /* allocate space for value */ - new_buf = realloc(buf, size); - if (!new_buf) { - const int err = errno; - fprintf(stderr, "Error: Could not resize buffer for reading column value. New size: %zu: %s (%d)\n", - size, strerror(err), err); - goto error; - } - - buf = new_buf; - curr = buf + curr_offset; + curr += TL; /* to go to start of value */ const size_t v = fread(curr, sizeof(char), value_len, pCur->output); if (v != value_len) { - fprintf(stderr, "Eror: Could not read %zu octets. Got %zu\n", value_len, v); + fprintf(stderr, "Error: Could not read %zu octets. Got %zu\n", value_len, v); goto error; } @@ -280,7 +257,7 @@ static int gufi_query_read_row(gufi_vtab_cursor *pCur) { } pCur->row = buf; - pCur->len = size; + pCur->len = row_len; pCur->col_starts = starts; pCur->col_count = count; diff --git a/src/print.c b/src/print.c index 5af32b810..58ca61102 100644 --- a/src/print.c +++ b/src/print.c @@ -86,7 +86,7 @@ int print_parallel(void *args, int count, char **data, char **columns) { } if (types) { - row_len += sizeof(count); /* start row with column count */ + row_len += sizeof(row_len) + sizeof(count); /* start row with row length and column count */ row_len += count * (sizeof(char) + sizeof(size_t)); /* type and length per column */ } else { @@ -111,8 +111,11 @@ int print_parallel(void *args, int count, char **data, char **columns) { pthread_mutex_lock(print->mutex); } - /* write column count */ if (types) { + /* write total row length */ + fwrite(&row_len, sizeof(char), sizeof(row_len), print->outfile); + + /* write column count */ fwrite(&count, sizeof(char), sizeof(count), print->outfile); } @@ -163,8 +166,12 @@ int print_parallel(void *args, int count, char **data, char **columns) { char *buf = ob->buf; size_t filled = ob->filled; - /* write column count */ if (types) { + /* write row length */ + memcpy(&buf[filled], &row_len, sizeof(row_len)); + filled += sizeof(row_len); + + /* write column count */ memcpy(&buf[filled], &count, sizeof(count)); filled += sizeof(count); } diff --git a/test/regression/gufi_query.expected b/test/regression/gufi_query.expected index 7cee5d1f2..6fbab9452 100644 --- a/test/regression/gufi_query.expected +++ b/test/regression/gufi_query.expected @@ -222,16 +222,17 @@ prefix/unusual#? directory ,/unusual, name?# # Output TLV columns (no aggregation) $ gufi_query -u -n 2 -E "SELECT name, size FROM vrpentries WHERE name == '.hidden';" "prefix" | od -x --endian=big -0000000 0200 0000 0307 0000 0000 0000 002e 6869 -0000020 6464 656e 0102 0000 0000 0000 0031 3000 -0000037 +0000000 2700 0000 0000 0000 0200 0000 0307 0000 +0000020 0000 0000 002e 6869 6464 656e 0102 0000 +0000040 0000 0000 0031 3000 +0000047 # Output TLV columns (with aggregation) $ gufi_query -u -d " " -n 2 -a -I "CREATE TABLE out(path TEXT, size INT64);" -K "CREATE TABLE aggregate(path TEXT, size INT64);" -S "INSERT INTO out SELECT rpath(sname, sroll), size FROM vrsummary;" -E "INSERT INTO out SELECT rpath(sname, sroll) || '/' || name, size FROM vrpentries;" -J "INSERT INTO aggregate SELECT path, size FROM out;" -G "SELECT path, size FROM aggregate ORDER BY path ASC LIMIT 1;" "prefix" | od -x --endian=big -0000000 0200 0000 030d 0000 0000 0000 0073 6561 -0000020 7263 682f 7072 6566 6978 0102 0000 0000 -0000040 0000 0031 3700 -0000045 +0000000 2d00 0000 0000 0000 0200 0000 030d 0000 +0000020 0000 0000 0073 6561 7263 682f 7072 6566 +0000040 6978 0102 0000 0000 0000 0031 3700 +0000055 ##################################### # Invalid Inputs # diff --git a/test/unit/googletest/print.cpp b/test/unit/googletest/print.cpp index 03f062784..f96fe5b3d 100644 --- a/test/unit/googletest/print.cpp +++ b/test/unit/googletest/print.cpp @@ -212,6 +212,7 @@ static void print_parallel_tlv_actual(const bool use_len) { }; const std::size_t total_len = + sizeof(std::size_t) + // row length sizeof(int) + // number of columns INTEGER.size() + FLOAT.size() + TEXT.size() + BLOB.size() + NULL_.size() + DATE.size() + @@ -242,6 +243,10 @@ static void print_parallel_tlv_actual(const bool use_len) { char *curr = buf; + // column_count + EXPECT_EQ((std::size_t) * (int *) curr, total_len); + curr += sizeof(std::size_t); + // column_count EXPECT_EQ((std::size_t) * (int *) curr, COL_COUNT); curr += sizeof(int);