Skip to content

Commit dd9ccbc

Browse files
Merge pull request #24 from jeromekelleher/buffer-safety-3
Buffer safety and refactoring
2 parents 5c35fa6 + e65fa4c commit dd9ccbc

File tree

3 files changed

+218
-118
lines changed

3 files changed

+218
-118
lines changed

lib/tests.c

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test_int_field_1d(void)
2020
.num_columns = 1,
2121
.data = (const char *) data };
2222
char buf[1000];
23-
const char *expected[] = { "1\t", "2\t", "12345789\t", ".\t", "-100\t" };
23+
const char *expected[] = { "1", "2", "12345789", ".", "-100" };
2424
int64_t ret;
2525
size_t j;
2626

@@ -43,15 +43,15 @@ test_int_field_1d_overflow(void)
4343
.item_size = 4,
4444
.num_columns = 1,
4545
.data = (const char *) data };
46-
int64_t ret;
47-
size_t j, buflen;
46+
int64_t ret, buflen;
47+
size_t j;
4848
char *buf;
4949

5050
for (j = 0; j < num_rows - 1; j++) {
5151
/* printf("%d\n", (int) data[j]); */
5252
for (buflen = 0; buflen <= VCZ_INT32_BUF_SIZE; buflen++) {
5353
/* printf("buflen = %d\n", (int) buflen); */
54-
buf = malloc(buflen);
54+
buf = malloc((size_t) buflen);
5555
CU_ASSERT_FATAL(buf != NULL);
5656
ret = vcz_field_write(&field, j, buf, buflen, 0);
5757
free(buf);
@@ -60,9 +60,9 @@ test_int_field_1d_overflow(void)
6060
}
6161
j = num_rows - 1;
6262
CU_ASSERT_FATAL(data[j] == -1);
63-
/* Missing data is treated differently. Just need 2 bytes for ".\t" */
64-
for (buflen = 0; buflen < 2; buflen++) {
65-
buf = malloc(buflen);
63+
/* Missing data is treated differently. Just need 1 byte for "." */
64+
for (buflen = 0; buflen < 1; buflen++) {
65+
buf = malloc((size_t) buflen);
6666
CU_ASSERT_FATAL(buf != NULL);
6767
ret = vcz_field_write(&field, j, buf, buflen, 0);
6868
free(buf);
@@ -81,7 +81,7 @@ test_int_field_2d(void)
8181
.num_columns = 3,
8282
.data = (const char *) data };
8383
char buf[1000];
84-
const char *expected[] = { "1,2,3\t", "1234,5678\t", ".\t", "\t" };
84+
const char *expected[] = { "1,2,3", "1234,5678", ".", "" };
8585
int64_t ret;
8686
size_t j;
8787

@@ -106,7 +106,7 @@ test_float_field_1d(void)
106106
.data = (const char *) data };
107107
char buf[1000];
108108
const char *expected[]
109-
= { "1\t", "2.1\t", "-2147483648\t", "12345789\t", "-1\t", "-100.123\t", ".\t" };
109+
= { "1", "2.1", "-2147483648", "12345789", "-1", "-100.123", "." };
110110
int64_t ret;
111111
size_t j;
112112
int32_t *int_data = (int32_t *) data;
@@ -115,8 +115,8 @@ test_float_field_1d(void)
115115

116116
for (j = 0; j < num_rows; j++) {
117117
ret = vcz_field_write(&field, j, buf, 1000, 0);
118-
printf("ret = %d\n", (int)ret);
119-
printf("'%.*s':'%s'\n", (int) ret, buf, expected[j]);
118+
/* printf("ret = %d\n", (int)ret); */
119+
/* printf("'%.*s':'%s'\n", (int) ret, buf, expected[j]); */
120120
CU_ASSERT_EQUAL_FATAL(ret, strlen(expected[j]));
121121
CU_ASSERT_NSTRING_EQUAL(buf, expected[j], ret);
122122
}
@@ -132,8 +132,8 @@ test_float_field_1d_overflow(void)
132132
.item_size = 4,
133133
.num_columns = 1,
134134
.data = (const char *) data };
135-
int64_t ret;
136-
size_t j, buflen;
135+
int64_t ret, buflen;
136+
size_t j;
137137
char *buf;
138138
int32_t *int_data = (int32_t *) data;
139139

@@ -143,17 +143,17 @@ test_float_field_1d_overflow(void)
143143
/* printf("%d\n", (int) data[j]); */
144144
for (buflen = 0; buflen <= VCZ_FLOAT32_BUF_SIZE; buflen++) {
145145
/* printf("buflen = %d\n", (int) buflen); */
146-
buf = malloc(buflen);
146+
buf = malloc((size_t) buflen);
147147
CU_ASSERT_FATAL(buf != NULL);
148148
ret = vcz_field_write(&field, j, buf, buflen, 0);
149149
free(buf);
150150
CU_ASSERT_FATAL(ret == VCZ_ERR_BUFFER_OVERFLOW);
151151
}
152152
}
153153
j = num_rows - 1;
154-
/* Missing data is treated differently. Just need 2 bytes for ".\t" */
155-
for (buflen = 0; buflen < 2; buflen++) {
156-
buf = malloc(buflen);
154+
/* Missing data is treated differently. Just need 1 byte for "." */
155+
for (buflen = 0; buflen < 1; buflen++) {
156+
buf = malloc((size_t) buflen);
157157
CU_ASSERT_FATAL(buf != NULL);
158158
ret = vcz_field_write(&field, j, buf, buflen, 0);
159159
free(buf);
@@ -176,15 +176,59 @@ test_string_field_1d(void)
176176
.num_columns = 1,
177177
.data = data };
178178
char buf[1000];
179-
const char *expected[] = { "X\t", "XX\t", "XXX\t" };
179+
const char *expected[] = { "X", "XX", "XXX" };
180180
int64_t ret;
181181
size_t j;
182182

183183
CU_ASSERT_EQUAL_FATAL(sizeof(data), 10);
184184
for (j = 0; j < num_rows; j++) {
185185
ret = vcz_field_write(&field, j, buf, 1000, 0);
186186
CU_ASSERT_EQUAL_FATAL(ret, strlen(expected[j]));
187-
CU_ASSERT_STRING_EQUAL(buf, expected[j]);
187+
CU_ASSERT_NSTRING_EQUAL(buf, expected[j], ret);
188+
}
189+
}
190+
191+
static void
192+
test_string_field_1d_overflow(void)
193+
{
194+
/* item_size=4, rows=3, cols=1 */
195+
const size_t num_rows = 4;
196+
const size_t item_size = 3;
197+
const char data[] = "X\0\0" /* X */
198+
"XX\0" /* XX*/
199+
"XXX" /* XXX, */
200+
".\0\0"; /* . */
201+
vcz_field_t field = { .name = "test",
202+
.type = VCZ_TYPE_STRING,
203+
.item_size = 3,
204+
.num_columns = 1,
205+
.data = data };
206+
int64_t ret, buflen;
207+
size_t j;
208+
char *buf;
209+
210+
for (j = 0; j < num_rows - 1; j++) {
211+
for (buflen = 0; buflen < (int) item_size; buflen++) {
212+
/* printf("buflen = %d\n", (int) buflen); */
213+
buf = malloc((size_t) buflen);
214+
CU_ASSERT_FATAL(buf != NULL);
215+
ret = vcz_field_write(&field, j, buf, buflen, 0);
216+
free(buf);
217+
if (ret < 0) {
218+
CU_ASSERT_FATAL(ret == VCZ_ERR_BUFFER_OVERFLOW);
219+
} else {
220+
CU_ASSERT_EQUAL_FATAL(ret, j + 1);
221+
}
222+
}
223+
}
224+
j = num_rows - 1;
225+
/* Missing data is treated differently. Just need 1 byte for "." */
226+
for (buflen = 0; buflen < 1; buflen++) {
227+
buf = malloc((size_t) buflen);
228+
CU_ASSERT_FATAL(buf != NULL);
229+
ret = vcz_field_write(&field, j, buf, buflen, 0);
230+
free(buf);
231+
CU_ASSERT_FATAL(ret == VCZ_ERR_BUFFER_OVERFLOW);
188232
}
189233
}
190234

@@ -196,14 +240,13 @@ test_string_field_2d(void)
196240
const char data[] = "X\0\0Y\0\0\0\0\0" /* [X, Y] */
197241
"XX\0YY\0Z\0\0" /* [XX, YY, Z], */
198242
"XXX\0\0\0\0\0"; /* [XXX], */
199-
200243
vcz_field_t field = { .name = "test",
201244
.type = VCZ_TYPE_STRING,
202245
.item_size = 3,
203246
.num_columns = 3,
204247
.data = data };
205248
char buf[1000];
206-
const char *expected[] = { "X,Y\t", "XX,YY,Z\t", "XXX\t" };
249+
const char *expected[] = { "X,Y", "XX,YY,Z", "XXX" };
207250
int64_t ret;
208251
size_t j;
209252

@@ -212,7 +255,7 @@ test_string_field_2d(void)
212255
for (j = 0; j < num_rows; j++) {
213256
ret = vcz_field_write(&field, j, buf, 1000, 0);
214257
CU_ASSERT_EQUAL_FATAL(ret, strlen(expected[j]));
215-
CU_ASSERT_STRING_EQUAL(buf, expected[j]);
258+
CU_ASSERT_NSTRING_EQUAL(buf, expected[j], ret);
216259
}
217260
}
218261

@@ -237,13 +280,13 @@ test_variant_encoder_minimal(void)
237280
const int32_t hq_data[] = { 10, 15, 7, 12, -1, -1, -1, -1 };
238281
const float gl_data[] = { 1, 2, 3, 4, 1.1f, 1.2f, 1.3f, 1.4f };
239282
int64_t ret;
240-
size_t j;
283+
size_t j, buflen;
241284
vcz_variant_encoder_t writer;
242285
const char *expected[] = {
243286
"X\t123\tRS1\tA\tT\t9\tPASS\tAA=G\tGT:HQ:GL\t0/0:10,15:1,2\t0|1:7,12:3,4",
244287
"YY\t45678\tRS2\tG\t.\t12.1\tFILT1\tAN=9;FLAG\tGT:GL\t1|1:1.1,1.2\t1/0:1.3,1.4",
245288
};
246-
char buf[1000];
289+
char *buf;
247290

248291
ret = vcz_variant_encoder_init(&writer, 2, 2, contig_data, 2, pos_data, id_data, 3,
249292
1, ref_data, 1, alt_data, 1, 1, qual_data, filter_id_data, 5, 2, filter_data);
@@ -270,14 +313,27 @@ test_variant_encoder_minimal(void)
270313
/* vcz_variant_encoder_print_state(&writer, stdout); */
271314

272315
for (j = 0; j < num_rows; j++) {
273-
ret = vcz_variant_encoder_write_row(&writer, j, buf, 1000);
274-
/* printf("ret = %d\n", ret); */
316+
for (buflen = 0;; buflen++) {
317+
/* printf("buflen = %d\n", (int) buflen); */
318+
buf = malloc(buflen);
319+
CU_ASSERT_FATAL(buf != NULL);
320+
ret = vcz_variant_encoder_write_row(&writer, j, buf, buflen);
321+
if (ret < 0) {
322+
free(buf);
323+
CU_ASSERT_EQUAL_FATAL(ret, VCZ_ERR_BUFFER_OVERFLOW);
324+
} else {
325+
break;
326+
}
327+
}
328+
CU_ASSERT_FATAL(buflen >= strlen(expected[j]));
329+
/* printf("ret = %d\n", (int) ret); */
275330
/* printf("GOT:%s\n", buf); */
276331
/* printf("EXP:%s\n", expected[j]); */
277332
/* printf("GOT:%d\n", (int) strlen(buf)); */
278333
/* printf("EXP:%d\n", (int) strlen(expected[j])); */
279334
CU_ASSERT_EQUAL(ret, strlen(expected[j]));
280335
CU_ASSERT_STRING_EQUAL(buf, expected[j]);
336+
free(buf);
281337
}
282338
vcz_variant_encoder_free(&writer);
283339
}
@@ -460,7 +516,8 @@ test_ftoa(void)
460516

461517
for (j = 0; j < sizeof(cases) / sizeof(*cases); j++) {
462518
len = vcz_ftoa(buf, cases[j].val);
463-
/* printf("j = %d %f->%s=='%s'\n", (int) j, cases[j].val, cases[j].expected, buf); */
519+
/* printf("j = %d %f->%s=='%s'\n", (int) j, cases[j].val, cases[j].expected,
520+
* buf); */
464521
CU_ASSERT_EQUAL_FATAL(len, strlen(cases[j].expected));
465522
CU_ASSERT_STRING_EQUAL_FATAL(buf, cases[j].expected);
466523
}
@@ -553,6 +610,7 @@ main(int argc, char **argv)
553610
{
554611
CU_TestInfo tests[] = {
555612
{ "test_string_field_1d", test_string_field_1d },
613+
{ "test_string_field_1d_overflow", test_string_field_1d_overflow },
556614
{ "test_string_field_2d", test_string_field_2d },
557615
{ "test_int_field_1d", test_int_field_1d },
558616
{ "test_int_field_1d_overflow", test_int_field_1d_overflow },

0 commit comments

Comments
 (0)