From 85e7bdf047cef16ccec0c1af6c4126d864e92ad9 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 20 Mar 2017 12:22:22 +0000 Subject: extend mime sniffing test coverage --- test/mimesniff.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 371 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/mimesniff.c b/test/mimesniff.c index 3e69589ad..5ce84c623 100644 --- a/test/mimesniff.c +++ b/test/mimesniff.c @@ -28,9 +28,20 @@ #include #include +#include "utils/utils.h" +#include "utils/corestrings.h" #include "content/content_factory.h" #include "content/mimesniff.h" +#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) + +struct test_mimetype { + const uint8_t* data; + const size_t len; + lwc_string **mime_type; + bool safe; +}; + /* helpers */ content_type content_factory_type_from_mime_type(lwc_string *mime_type) { @@ -38,13 +49,40 @@ content_type content_factory_type_from_mime_type(lwc_string *mime_type) return type; } +/* Fixtures */ + +static void corestring_create(void) +{ + ck_assert(corestrings_init() == NSERROR_OK); +} +/** + * iterator for any remaining strings in teardown fixture + */ +static void netsurf_lwc_iterator(lwc_string *str, void *pw) +{ + fprintf(stderr, + "[%3u] %.*s", + str->refcnt, + (int)lwc_string_length(str), + lwc_string_data(str)); +} + +static void corestring_teardown(void) +{ + corestrings_fini(); + + lwc_iterate_strings(netsurf_lwc_iterator, NULL); +} + +/* tests */ START_TEST(mimesniff_api_test) { nserror err; lwc_string *effective_type; + /* no header type, no data and sniffing not allowed */ err = mimesniff_compute_effective_type(NULL, NULL, 0, @@ -53,14 +91,24 @@ START_TEST(mimesniff_api_test) &effective_type); ck_assert(err == NSERROR_NOT_FOUND); + /* no header type, no data and sniffing allowed */ + err = mimesniff_compute_effective_type(NULL, + NULL, + 0, + true, + false, + &effective_type); + ck_assert(err == NSERROR_NEED_DATA); + } END_TEST -static TCase *mimesniff_case_create(void) +static TCase *mimesniff_api_case_create(void) { TCase *tc; - tc = tcase_create("mimesniff"); + tc = tcase_create("mimesniff API"); + tcase_add_test(tc, mimesniff_api_test); @@ -68,12 +116,332 @@ static TCase *mimesniff_case_create(void) } +/* unknown header exact binary type checks in safe context */ +#define SIG(s,m,a) { (const uint8_t *)s, SLEN(s), &corestring_lwc_##m, a } +static struct test_mimetype match_unknown_exact_tests[] = { + SIG("GIF87a", image_gif, true), + SIG("GIF89a", image_gif, true), + SIG("\x89PNG\r\n\x1a\n", image_png, true), + SIG("\xff\xd8\xff", image_jpeg, true), + SIG("BM", image_bmp, true), + SIG("\x00\x00\x01\x00", image_vnd_microsoft_icon, true), + SIG("OggS\x00", application_ogg, true), + SIG("\x1a\x45\xdf\xa3", video_webm, true), + SIG("Rar \x1a\x07\x00", application_x_rar_compressed, true), + SIG("PK\x03\x04", application_zip, true), + SIG("\x1f\x8b\x08", application_x_gzip, true), + SIG("%!PS-Adobe-", application_postscript, true), + SIG("%PDF-", application_pdf, false), +}; + +static struct test_mimetype match_unknown_riff_tests[] = { + SIG("RIFF WEBPVP", image_webp, true), + SIG("RIFF WAVE", audio_wave, true), +}; + +static struct test_mimetype match_unknown_bom_tests[] = { + SIG("\xfe\xff",text_plain, false), + SIG("\xff\xfe", text_plain, false), + SIG("\xef\xbb\xbf", text_plain, false), +}; + +static struct test_mimetype match_unknown_ws_tests[] = { + SIG("data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/** + * riff test + */ +START_TEST(mimesniff_match_unknown_riff_test) +{ + nserror err; + const struct test_mimetype *tst = &match_unknown_riff_tests[_i]; + lwc_string *effective_type; + bool match; + + err = mimesniff_compute_effective_type(NULL, + tst->data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/** + * BOM test + */ +START_TEST(mimesniff_match_unknown_bom_test) +{ + nserror err; + const struct test_mimetype *tst = &match_unknown_bom_tests[_i]; + lwc_string *effective_type; + bool match; + + err = mimesniff_compute_effective_type(NULL, + tst->data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/** + * ws test + */ +START_TEST(mimesniff_match_unknown_ws_test) +{ + nserror err; + const struct test_mimetype *tst = &match_unknown_ws_tests[_i]; + lwc_string *effective_type; + bool match; + + err = mimesniff_compute_effective_type(NULL, + tst->data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/** + * ws test + */ +START_TEST(mimesniff_match_unknown_mp4_test) +{ + nserror err; + const struct test_mimetype *tst = &match_unknown_mp4_tests[_i]; + lwc_string *effective_type; + bool match; + + err = mimesniff_compute_effective_type(NULL, + tst->data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/** + * unknown header text/binary test + */ +START_TEST(mimesniff_match_unknown_txtbin_test) +{ + nserror err; + const struct test_mimetype *tst = &match_unknown_txtbin_tests[_i]; + lwc_string *effective_type; + bool match; + + err = mimesniff_compute_effective_type(NULL, + tst->data, + tst->len, + true, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + *(tst->mime_type), + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + + +static TCase *mimesniff_match_unknown_case_create(void) +{ + TCase *tc; + tc = tcase_create("mimesniff"); + + tcase_add_unchecked_fixture(tc, + corestring_create, + corestring_teardown); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_exact_test, + 0, NELEMS(match_unknown_exact_tests)); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_riff_test, + 0, NELEMS(match_unknown_riff_tests)); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_bom_test, + 0, NELEMS(match_unknown_bom_tests)); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_ws_test, + 0, NELEMS(match_unknown_ws_tests)); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_mp4_test, + 0, NELEMS(match_unknown_mp4_tests)); + + tcase_add_loop_test(tc, + mimesniff_match_unknown_txtbin_test, + 0, NELEMS(match_unknown_txtbin_tests)); + + return tc; +} + + +START_TEST(mimesniff_unparsable_header_test) +{ + nserror err; + lwc_string *effective_type; + + /* unparsable header type, no data and sniffing not allowed */ + err = mimesniff_compute_effective_type("badheader", + NULL, + 0, + false, + false, + &effective_type); + ck_assert_int_eq(err, NSERROR_NOT_FOUND); + + /* unparsable header type, no data and sniffing allowed */ + err = mimesniff_compute_effective_type("badheader", + NULL, + 0, + true, + false, + &effective_type); + ck_assert_int_eq(err, NSERROR_NEED_DATA); + +} +END_TEST + + +START_TEST(mimesniff_parsable_header_nosniff_test) +{ + nserror err; + lwc_string *effective_type; + bool match; + + /* unparsable header type, no data and sniffing not allowed */ + err = mimesniff_compute_effective_type("text/plain", + NULL, + 0, + false, + false, + &effective_type); + ck_assert(err == NSERROR_OK); + + ck_assert(lwc_string_caseless_isequal(effective_type, + corestring_lwc_text_plain, + &match) == lwc_error_ok && match); + lwc_string_unref(effective_type); +} +END_TEST + +/* test cases with header mime type */ +static TCase *mimesniff_header_case_create(void) +{ + TCase *tc; + tc = tcase_create("mimesniff header"); + + tcase_add_unchecked_fixture(tc, + corestring_create, + corestring_teardown); + + tcase_add_test(tc, mimesniff_unparsable_header_test); + tcase_add_test(tc, mimesniff_parsable_header_nosniff_test); + + return tc; +} + + static Suite *mimesniff_suite_create(void) { Suite *s; s = suite_create("mime sniffing"); - suite_add_tcase(s, mimesniff_case_create()); + suite_add_tcase(s, mimesniff_api_case_create()); + suite_add_tcase(s, mimesniff_match_unknown_case_create()); + suite_add_tcase(s, mimesniff_header_case_create()); return s; } -- cgit v1.2.3