mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-05-02 02:11:13 +00:00
535 lines
13 KiB
C
535 lines
13 KiB
C
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
/*
|
|
* test-csv.c - test our csv parser
|
|
*/
|
|
|
|
#ifndef SHIM_UNIT_TEST
|
|
#define SHIM_UNIT_TEST
|
|
#endif
|
|
#include "shim.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
struct test_entry {
|
|
size_t n_columns;
|
|
char *columns[7];
|
|
};
|
|
|
|
int
|
|
test_parse_csv_line_size_0(void)
|
|
{
|
|
char *s0 = "";
|
|
char *columns[] = { "a", "b", "c", "d" };
|
|
char *test_columns[] = { NULL, NULL, NULL, NULL };
|
|
size_t n_columns = 3;
|
|
size_t i;
|
|
|
|
test_columns[3] = columns[3];
|
|
|
|
parse_csv_line(s0, 0, &n_columns, (const char **)columns);
|
|
|
|
assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(n_columns, 0, -1, "got %#hhx expected %#hhx\n");
|
|
for (i = 0; i < 4; i++) {
|
|
assert_equal_return(test_columns[i], columns[i], -1,
|
|
"expected %p got %p for column %d\n",
|
|
i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
test_parse_csv_line_size_1(void)
|
|
{
|
|
char *s0 = "";
|
|
char *columns[] = { "a", "b", "c", "d" };
|
|
char *test_columns[] = { "", NULL, NULL, NULL };
|
|
size_t n_columns = 3;
|
|
size_t max = 1;
|
|
size_t i;
|
|
|
|
test_columns[3] = columns[3];
|
|
|
|
parse_csv_line(s0, max, &n_columns, (const char **)columns);
|
|
|
|
assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n");
|
|
for (i = 0; i < 4; i++) {
|
|
assert_equal_return(test_columns[i], columns[i], -1,
|
|
"expected %p got %p for column %d\n",
|
|
i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
test_parse_csv_line_comma_size_1(void)
|
|
{
|
|
char *s0;
|
|
char *columns[] = { "a", "b", "c", "d" };
|
|
char *test_columns[] = { "", NULL, NULL, "d" };
|
|
size_t n_columns = 3;
|
|
size_t max = 1;
|
|
size_t i;
|
|
|
|
/*
|
|
* For reasons unknown, when I do this the normal way with:
|
|
* char *s0 = ",";
|
|
* gcc is putting it in .rodata,
|
|
* *** AND combining it with the "," from delims from parse_csv_line***.
|
|
*/
|
|
s0 = alloca(2);
|
|
s0[0] = ',';
|
|
s0[1] = '\0';
|
|
|
|
parse_csv_line(s0, max, &n_columns, (const char **)columns);
|
|
|
|
assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n");
|
|
// for (i = 0; i < 4; i++) {
|
|
// printf("columns[%d]:%p:\"%s\"\n", i, columns[i], columns[i]);
|
|
// }
|
|
for (i = 0; i < 1; i++) {
|
|
assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
|
|
"expected %d got %d for column %d\n", i);
|
|
}
|
|
for (i = 1; i < 3; i++) {
|
|
assert_equal_return(test_columns[i], columns[i], -1,
|
|
"expected %p got %p for column %d\n",
|
|
i);
|
|
}
|
|
for (i = 3; i < 4; i++) {
|
|
assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
|
|
"expected %d got %d for column %d\n", i);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
test_parse_csv_line_comma_size_2(void)
|
|
{
|
|
char *s0;
|
|
char *columns[] = { "a", "b", "c", "d" };
|
|
char *test_columns[] = { "", "", NULL, "d" };
|
|
size_t n_columns = 3;
|
|
size_t max = 2;
|
|
size_t i;
|
|
|
|
/*
|
|
* For reasons unknown, when I do this the normal way with:
|
|
* char *s0 = ",";
|
|
* gcc is putting it in .rodata,
|
|
* *** AND combining it with the "," from delims from parse_csv_line***.
|
|
*/
|
|
s0 = alloca(2);
|
|
s0[0] = ',';
|
|
s0[1] = '\0';
|
|
|
|
parse_csv_line(s0, max, &n_columns, (const char **)columns);
|
|
|
|
assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(n_columns, 2, -1, "got %#hhx expected %#hhx\n");
|
|
for (i = 0; i < 2; i++) {
|
|
assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
|
|
"expected %d got %d for column %d\n", i);
|
|
}
|
|
for (i = 2; i < 3; i++) {
|
|
assert_equal_return(test_columns[i], columns[i], -1,
|
|
"expected %p got %p for column %d\n",
|
|
i);
|
|
}
|
|
for (i = 3; i < 4; i++) {
|
|
assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
|
|
"expected %d got %d for column %d\n", i);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
test_csv_0(void)
|
|
{
|
|
char csv[] =
|
|
"\000\000\000"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c\n"
|
|
"\n"
|
|
"\n"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c";
|
|
struct test_entry test_entries[]= {
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
};
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE);
|
|
|
|
current = csv;
|
|
end = csv + sizeof(csv) - 1;
|
|
|
|
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
struct test_entry *test_entry = &test_entries[i++];
|
|
size_t j;
|
|
|
|
assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i);
|
|
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
|
|
assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
|
|
fail, "got %d expected %d\n");
|
|
for (j = 0; j < csv_row->n_columns; j++) {
|
|
assert_equal_goto(strcmp(csv_row->columns[j],
|
|
test_entry->columns[j]), 0,
|
|
fail, "got %d expected %d\n");
|
|
}
|
|
}
|
|
|
|
assert_equal_return(list_size(&entry_list), 4, -1,
|
|
"got %d expected %d\n");
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
test_csv_1(void)
|
|
{
|
|
char csv[] =
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c\n"
|
|
"\n"
|
|
"\n"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c";
|
|
struct test_entry test_entries[]= {
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
};
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
current = csv;
|
|
end = csv + sizeof(csv) - 1;
|
|
|
|
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
struct test_entry *test_entry = &test_entries[i++];
|
|
size_t j;
|
|
|
|
assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i);
|
|
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
|
|
assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
|
|
fail, "got %d expected %d\n");
|
|
for (j = 0; j < csv_row->n_columns; j++) {
|
|
assert_equal_goto(strcmp(csv_row->columns[j],
|
|
test_entry->columns[j]), 0,
|
|
fail, "got %d expected %d\n");
|
|
}
|
|
}
|
|
|
|
assert_equal_return(list_size(&entry_list), 4, -1,
|
|
"got %d expected %d\n");
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
test_csv_2(void)
|
|
{
|
|
char csv[] =
|
|
"\000\000\000"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,c\n"
|
|
"\n"
|
|
"\n"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c";
|
|
struct test_entry test_entries[]= {
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 7, { "", "", "", "", "", "", "" } },
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
};
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE);
|
|
|
|
current = csv;
|
|
end = csv + sizeof(csv) - 1;
|
|
|
|
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
struct test_entry *test_entry = &test_entries[i++];
|
|
size_t j;
|
|
|
|
assert_goto(i > 0 && i <= 7, fail, "got %d expected 0 to 7\n", i);
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
|
|
assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
|
|
fail, "got %d expected %d\n");
|
|
for (j = 0; j < csv_row->n_columns; j++) {
|
|
assert_equal_goto(strcmp(csv_row->columns[j],
|
|
test_entry->columns[j]), 0,
|
|
fail, "got %d expected %d\n");
|
|
}
|
|
}
|
|
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
test_csv_3(void)
|
|
{
|
|
char csv[] =
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c\n"
|
|
"\n"
|
|
"\n"
|
|
"a,b,c,d,e,f,g,h\n"
|
|
"a,b,c\0x,y\0z\0";
|
|
struct test_entry test_entries[]= {
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
{ 7, { "a", "b", "c", "d", "e", "f", "g" } },
|
|
{ 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
|
|
};
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
current = csv;
|
|
end = csv + sizeof(csv) - 1;
|
|
|
|
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
struct test_entry *test_entry = &test_entries[i++];
|
|
size_t j;
|
|
|
|
assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i);
|
|
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
|
|
assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
|
|
fail, "got %d expected %d\n");
|
|
for (j = 0; j < csv_row->n_columns; j++) {
|
|
assert_equal_goto(strcmp(csv_row->columns[j],
|
|
test_entry->columns[j]), 0,
|
|
fail, "got %d expected %d\n");
|
|
}
|
|
}
|
|
|
|
assert_equal_return(list_size(&entry_list), 4, -1,
|
|
"got %d expected %d\n");
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
test_simple_sbat_csv(void)
|
|
{
|
|
char csv[] =
|
|
"test1,1,SBAT test1,acme1,1,testURL1\n"
|
|
"test2,2,SBAT test2,acme2,2,testURL2\n";
|
|
struct test_entry test_entries[]= {
|
|
{ 6, { "test1", "1", "SBAT test1", "acme1", "1", "testURL1" } },
|
|
{ 6, { "test2", "2", "SBAT test2", "acme2", "2", "testURL2" } },
|
|
};
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
current = csv;
|
|
end = csv + sizeof(csv) - 1;
|
|
|
|
efi_status = parse_csv_data(current, end, 6, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1,
|
|
"got %d expected %d\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
struct test_entry *test_entry = &test_entries[i++];
|
|
size_t j;
|
|
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
|
|
assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
|
|
fail, "got %d expected %d");
|
|
|
|
for (j = 0; j < csv_row->n_columns; j++) {
|
|
assert_equal_goto(strcmp(csv_row->columns[j],
|
|
test_entry->columns[j]), 0,
|
|
fail, "got %d expected %d\n");
|
|
}
|
|
}
|
|
|
|
assert_equal_return(list_size(&entry_list), 2, -1,
|
|
"got %d expected %d\n");
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
|
|
}
|
|
|
|
int
|
|
test_csv_simple_fuzz(char *random_bin, size_t random_bin_len,
|
|
bool assert_entries)
|
|
{
|
|
list_t entry_list;
|
|
size_t i;
|
|
char *current, *end;
|
|
list_t *pos = NULL;
|
|
EFI_STATUS efi_status;
|
|
|
|
INIT_LIST_HEAD(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
current = &random_bin[0];
|
|
current = current + 1 - 1;
|
|
end = current + random_bin_len - 1;
|
|
*end = '\0';
|
|
|
|
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
|
assert_equal_return(efi_status, EFI_SUCCESS, -1, "expected %#x got %#x\n");
|
|
printf("parsed %zd entries\n", list_size(&entry_list));
|
|
if (assert_entries)
|
|
assert_goto(list_size(&entry_list) > 0, fail,
|
|
"expected >0 entries\n");
|
|
|
|
i = 0;
|
|
list_for_each(pos, &entry_list) {
|
|
struct csv_row *csv_row;
|
|
|
|
csv_row = list_entry(pos, struct csv_row, list);
|
|
dprint("row[%zd]: %zd columns\n", i, csv_row->n_columns);
|
|
i++;
|
|
}
|
|
|
|
free_csv_list(&entry_list);
|
|
assert_equal_return(list_size(&entry_list), 0, -1,
|
|
"got %d expected %d\n");
|
|
|
|
return 0;
|
|
fail:
|
|
free_csv_list(&entry_list);
|
|
return -1;
|
|
}
|
|
|
|
#include "test-random.h"
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int status = 0;
|
|
size_t i, j;
|
|
|
|
setbuf(stdout, NULL);
|
|
test(test_parse_csv_line_size_0);
|
|
test(test_parse_csv_line_size_1);
|
|
test(test_parse_csv_line_comma_size_1);
|
|
test(test_parse_csv_line_comma_size_2);
|
|
test(test_csv_0);
|
|
test(test_csv_1);
|
|
test(test_csv_2);
|
|
test(test_csv_3);
|
|
test(test_simple_sbat_csv);
|
|
test(test_csv_simple_fuzz, random_bin, random_bin_len, false);
|
|
for (i = 0; i < random_bin_len; i++) {
|
|
j = i;
|
|
while (random_bin[i] == '\0')
|
|
random_bin[i] = j++;
|
|
}
|
|
test(test_csv_simple_fuzz, random_bin, random_bin_len, true);
|
|
|
|
return status;
|
|
}
|
|
|
|
// vim:fenc=utf-8:tw=75:noet
|