#include #include #include #include #include #include static int _print(const void *buffer, size_t size, void *app_key) { (void)app_key; fwrite(buffer, size, 1, stdout); return 0; } static void check_OID(int lineno, uint8_t *buf, size_t len, unsigned *ck_buf, int ck_len) { OBJECT_IDENTIFIER_t *oid; asn_dec_rval_t rval; uint32_t arcs[11]; int alen; int i; printf("%03d: Checking {", lineno); for(i = 0; i < (int)len; i++) { printf("%s%02x", i?" ":"", buf[i]); } printf("} against {"); for(i = 0; i < ck_len; i++) { printf("%s%u", i?" ":"", ck_buf[i]); } printf("}\n"); oid = NULL; rval = ber_decode(0, &asn_DEF_OBJECT_IDENTIFIER, (void *)&oid, buf, len); assert(rval.code == RC_OK); assert((ssize_t)oid->size == (ssize_t)len - 2); /* * Print the contents for visual debugging. */ printf("OBJECT_IDENTIFIER_print() => "); OBJECT_IDENTIFIER_print(&asn_DEF_OBJECT_IDENTIFIER, oid, 0, _print, 0); printf("\n"); memset(arcs, 'A', sizeof(arcs)); alen = OBJECT_IDENTIFIER_get_arcs(oid, arcs, sizeof(arcs) / sizeof(arcs[0])); assert(alen > 0); printf("OBJECT_IDENTIFIER_get_arcs() => {"); /* * Make sure they are equivalent. */ for(i = 0; i < alen; i++) { printf(" %" PRIu32, arcs[i]); if(alen == ck_len) { assert(arcs[i] == ck_buf[i]); } } printf(" }\n"); assert(alen == ck_len); ASN_STRUCT_FREE(asn_DEF_OBJECT_IDENTIFIER, oid); } static void check_ROID(int lineno, uint8_t *buf, size_t len, unsigned *ck_buf, size_t ck_len) { RELATIVE_OID_t *oid; asn_dec_rval_t rval; uint32_t arcs[10]; int alen; size_t i; printf("%03d: Checking {", lineno); for(i = 0; i < len; i++) { printf("%s%02x", i?" ":"", buf[i]); } printf("} against {"); for(i = 0; i < ck_len; i++) { printf("%s%u", i?" ":"", ck_buf[i]); } printf("}\n"); oid = NULL; rval = ber_decode(0, &asn_DEF_RELATIVE_OID, (void *)&oid, buf, len); assert(rval.code == RC_OK); assert((ssize_t)oid->size == (ssize_t)len - 2); /* * Print the contents for visual debugging. */ printf("RELATIVE_OID_print() => "); RELATIVE_OID_print(&asn_DEF_RELATIVE_OID, oid, 0, _print, 0); printf("\n"); memset(arcs, 'A', sizeof(arcs)); alen = RELATIVE_OID_get_arcs(oid, arcs, sizeof(arcs) / sizeof(arcs[0])); assert(alen > 0); assert((size_t)alen == ck_len); /* * Make sure they are equivalent. */ printf("RELATIVE_OID_get_arcs() => {"); for(i = 0; i < (size_t)alen; i++) { printf(" %" PRIu32, arcs[i]); assert(arcs[i] == ck_buf[i]); } printf(" }\n"); ASN_STRUCT_FREE(asn_DEF_RELATIVE_OID, oid); } static int check_speed() { uint8_t buf[] = { 0x80 | 7, 0x80 | 2, 0x80 | 3, 0x80 | 4, 13 }; int ret = 0; int cycles = 100000000; double a, b, c; struct timeval tv; uint32_t value; int i; ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value); assert(ret == 0); assert(value == 0x7040c20d); gettimeofday(&tv, 0); a = tv.tv_sec + tv.tv_usec / 1000000.0; for(i = 0; i < cycles; i++) { ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value); } assert(ret == 0); assert(value == 0x7040c20d); gettimeofday(&tv, 0); b = tv.tv_sec + tv.tv_usec / 1000000.0; for(i = 0; i < cycles; i++) { ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value); } assert(ret == 0); assert(value == 0x7040c20d); gettimeofday(&tv, 0); c = tv.tv_sec + tv.tv_usec / 1000000.0; a = b - a; b = c - b; printf("Time for single_arc(): %f\n", a); printf("Time for get_arc_l(): %f\n", b); return 0; } #define CHECK_PARSE(a, b) check_parse(__LINE__, a, b) static void check_parse(int lineno, const char *oid_txt, int retval) { int ret; uint32_t arcs[2]; const char *p = oid_txt - 13; assert(p < oid_txt); ret = OBJECT_IDENTIFIER_parse_arcs(oid_txt, -1, arcs, 2, &p); printf("%03d: [%s] => %d == %d\n", lineno, oid_txt, ret, retval); assert(ret == retval); assert(p >= oid_txt); } static void check_xer(int lineno, asn_TYPE_descriptor_t *td, ssize_t expect_arcs, char *xer, const asn_oid_arc_t *expected_arcs) { asn_dec_rval_t rc; void *st = 0; uint32_t arcs[10]; ssize_t got_arcs; ssize_t i; printf("%03d: [%s] => ", lineno, xer); fflush(stdout); rc = td->op->xer_decoder(0, td, (void **)&st, "t", xer, strlen(xer)); if(expect_arcs == -1) { if(rc.code != RC_OK) { printf("-1\n"); ASN_STRUCT_FREE(*td, st); return; } } assert(rc.code == RC_OK); if(td == &asn_DEF_OBJECT_IDENTIFIER) { got_arcs = OBJECT_IDENTIFIER_get_arcs(st, arcs, sizeof(arcs) / sizeof(arcs[0])); } else if(td == &asn_DEF_RELATIVE_OID) { got_arcs = RELATIVE_OID_get_arcs(st, arcs, sizeof(arcs) / sizeof(arcs[0])); } else { assert(!"Unreachable"); } assert(got_arcs < 10); if(expect_arcs == -1) { assert(got_arcs == -1); ASN_STRUCT_FREE(*td, st); return; } for(i = 0; i < got_arcs; i++) { if(i) printf("."); printf("%" PRIu32, arcs[i]); if(arcs[i] != expected_arcs[i]) { printf(" != %" PRIu32 "\n", expected_arcs[i]); } assert(arcs[i] == expected_arcs[i]); } printf(": %zd == %zd\n", got_arcs, expect_arcs); assert(got_arcs == expect_arcs); ASN_STRUCT_FREE(*td, st); } #define CHECK_OID(n) \ check_OID(__LINE__, buf##n, sizeof(buf##n), buf##n##_check, \ sizeof(buf##n##_check) / sizeof(buf##n##_check[0])) #define CHECK_ROID(n) \ check_ROID(__LINE__, buf##n, sizeof(buf##n), buf##n##_check, \ sizeof(buf##n##_check) / sizeof(buf##n##_check[0])) static void check_binary_parsing() { /* {0 0} */ uint8_t buf0[] = { 0x06, /* OBJECT IDENTIFIER */ 0x01, /* Length */ 0x00 }; uint32_t buf0_check[] = { 0, 0 }; /* {joint-iso-itu-t 230 3} */ uint8_t buf1[] = { 0x06, /* OBJECT IDENTIFIER */ 0x03, /* Length */ 0x82, 0x36, 0x03 }; uint32_t buf1_check[] = { 2, 230, 3 }; /* {joint-iso-itu-t 42 } */ uint8_t buf2[] = { 0x06, /* OBJECT IDENTIFIER */ 0x01, /* Length */ 0x7A }; uint32_t buf2_check[] = { 2, 42 }; /* {joint-iso-itu-t 25957 } */ uint8_t buf3[] = { 0x06, /* OBJECT IDENTIFIER */ 0x03, /* Length */ 0x81, 0x80 + 0x4B, 0x35 }; uint32_t buf3_check[] = { 2, 25957 }; /* { jounsigned-iso-itu-t 2 1 1 } */ uint8_t buf4[] = { 0x06, /* OBJECT IDENTIFIER */ 0x03, /* Length */ 0x52, 0x01, 0x01 }; uint32_t buf4_check[] = { 2, 2, 1, 1 }; /* { jounsigned-iso-itu-t 2 1 0 1 } */ uint8_t buf5[] = { 0x06, /* OBJECT IDENTIFIER */ 0x04, /* Length */ 0x52, 0x01, 0x00, 0x01 }; uint32_t buf5_check[] = { 2, 2, 1, 0, 1 }; /* {joint-iso-itu-t 25957 } */ uint8_t buf6[] = { 0x06, /* OBJECT IDENTIFIER */ 0x0c, /* Length */ 0x2a, 0x03, 0x01, 0x01, 0x01, 0x81, 0xaa, 0x11, 0x03, 0x05, 0x01, 0x01 }; uint32_t buf6_check[] = { 1, 2, 3, 1, 1, 1, 21777, 3, 5, 1, 1 }; /* {0 0} */ uint8_t buf10[] = { 0x0D, /* RELATIVE-OID */ 0x01, /* Length */ 0x00 }; uint32_t buf10_check[] = { 0 }; /* {0 0} */ uint8_t buf11[] = { 0x0D, /* RELATIVE-OID */ 0x02, /* Length */ 0x00, 0x00 }; uint32_t buf11_check[] = { 0, 0 }; /* {8571 3 2} */ uint8_t buf12[] = { 0x0D, /* RELATIVE-OID */ 0x04, /* Length */ 0xC2, 0x7B, 0x03, 0x02 }; uint32_t buf12_check[] = { 8571, 3, 2 }; CHECK_OID(0); CHECK_OID(1); CHECK_OID(2); CHECK_OID(3); CHECK_OID(4); CHECK_OID(5); CHECK_OID(6); CHECK_ROID(10); CHECK_ROID(11); CHECK_ROID(12); } static void check_text_parsing() { CHECK_PARSE("", 0); CHECK_PARSE(" ", 0); CHECK_PARSE(".", -1); CHECK_PARSE(" .", -1); CHECK_PARSE(".1", -1); CHECK_PARSE("1.", -1); CHECK_PARSE("1. ", -1); CHECK_PARSE(".1. ", -1); CHECK_PARSE(" .1. ", -1); CHECK_PARSE(" 1", 1); CHECK_PARSE(" 1.2", 2); CHECK_PARSE(" 1.", -1); CHECK_PARSE(" 1. ", -1); CHECK_PARSE("1. ", -1); CHECK_PARSE("1.2", 2); CHECK_PARSE("1.2 ", 2); CHECK_PARSE("1.2 ", 2); CHECK_PARSE(" 1.2 ", 2); CHECK_PARSE("1. 2", -1); CHECK_PARSE("1 .2", -1); CHECK_PARSE(" 1 .2", -1); CHECK_PARSE(" 1 .2 ", -1); CHECK_PARSE("1 .2 ", -1); CHECK_PARSE("1.+1", -1); CHECK_PARSE("2.0", 2); CHECK_PARSE("2.1", 2); CHECK_PARSE("10.30.234.234", 4); CHECK_PARSE("10.30.234.234 ", 4); CHECK_PARSE("10.30.234. 234 ", -1); CHECK_PARSE("10.30.234.234.", -1); CHECK_PARSE("1.2000000000.3", 3); CHECK_PARSE("1.2147483647.3", 3); CHECK_PARSE("1.4294967295.3", 3); CHECK_PARSE("1.4294967296.3", -1); /* overflow on ILP32 */ CHECK_PARSE("1.3000000000.3", 3); CHECK_PARSE("1.4000000000.3", 3); CHECK_PARSE("1.5000000000.3", -1); CHECK_PARSE("1.6000000000.3", -1); CHECK_PARSE("1.9000000000.3", -1); CHECK_PARSE("1.900a0000000.3", -1); CHECK_PARSE("1.900a.3", -1); } #define CHECK_XER(a, b, c, data) check_xer(__LINE__, &asn_DEF_##a, b, c, data) static void check_xer_parsing() { asn_oid_arc_t zero_zero[] = {0, 0}; asn_oid_arc_t zero_one[] = {0, 1}; asn_oid_arc_t one_zero[] = {1, 0}; asn_oid_arc_t one_one[] = {1, 1}; asn_oid_arc_t one_two[] = {1, 2}; asn_oid_arc_t two_one[] = {2, 1}; asn_oid_arc_t one_two_three[] = {1, 2,3}; CHECK_XER(RELATIVE_OID, -1, "", 0); CHECK_XER(RELATIVE_OID, -1, "1.", 0); CHECK_XER(RELATIVE_OID, -1, "2.1.", 0); CHECK_XER(RELATIVE_OID, 2, "0.0", zero_zero); CHECK_XER(RELATIVE_OID, 2, "0.1", zero_one); CHECK_XER(RELATIVE_OID, 2, "1.0", one_zero); CHECK_XER(RELATIVE_OID, 2, "1.2", one_two); CHECK_XER(RELATIVE_OID, -1, "1.-2", 0); CHECK_XER(RELATIVE_OID, -1, "1.+2", 0); CHECK_XER(RELATIVE_OID, 3, "1.2.3", one_two_three); CHECK_XER(RELATIVE_OID, 3, " 1.2.3 ", one_two_three); CHECK_XER(RELATIVE_OID, -1, "1.2.3 1", 0); CHECK_XER(RELATIVE_OID, 2, "2.1", two_one); CHECK_XER(OBJECT_IDENTIFIER, -1, "", 0); CHECK_XER(OBJECT_IDENTIFIER, -1, "1", 0); CHECK_XER(OBJECT_IDENTIFIER, -1, "1.", 0); CHECK_XER(OBJECT_IDENTIFIER, -1, "2.1.", 0); CHECK_XER(OBJECT_IDENTIFIER, 2, "0.0", zero_zero); CHECK_XER(OBJECT_IDENTIFIER, 2, "0.1", zero_one); CHECK_XER(OBJECT_IDENTIFIER, 2, "1.0", one_zero); CHECK_XER(OBJECT_IDENTIFIER, 2, "1.1", one_one); CHECK_XER(OBJECT_IDENTIFIER, 2, "1.2", one_two); CHECK_XER(OBJECT_IDENTIFIER, -1, "1.-2", 0); CHECK_XER(OBJECT_IDENTIFIER, -1, "1.+2", 0); CHECK_XER(OBJECT_IDENTIFIER, 3, "1.2.3", one_two_three); CHECK_XER(OBJECT_IDENTIFIER, 3, " 1.2.3 ", one_two_three); CHECK_XER(OBJECT_IDENTIFIER, -1, "1.2.3 1", 0); CHECK_XER(OBJECT_IDENTIFIER, 2, " 2.1 ", two_one); } int main() { check_binary_parsing(); check_text_parsing(); check_xer_parsing(); if(getenv("CHECK_SPEED")) { /* Useful for developers only */ check_speed(); } return 0; }