Fix ASN.1 template compiler bug and add test cases more likely to trip on similar (structure size/type) errors
Signed-off-by: Roland C. Dowdeswell <elric@imrryr.org>
This commit is contained in:
		 Viktor Dukhovni
					Viktor Dukhovni
				
			
				
					committed by
					
						 Roland C. Dowdeswell
						Roland C. Dowdeswell
					
				
			
			
				
	
			
			
			 Roland C. Dowdeswell
						Roland C. Dowdeswell
					
				
			
						parent
						
							0fad20a7ce
						
					
				
				
					commit
					5e081aa4a6
				
			| @@ -60,7 +60,7 @@ static char *nada_tgt_principal[] = { "krbtgt", "NADA.KTH.SE" }; | ||||
|  | ||||
|  | ||||
| #define IF_OPT_COMPARE(ac,bc,e) \ | ||||
| 	if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; if ((ab)->e) | ||||
| 	if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; if ((ac)->e) | ||||
| #define COMPARE_OPT_STRING(ac,bc,e) \ | ||||
| 	do { if (strcmp(*(ac)->e, *(bc)->e) != 0) return 1; } while(0) | ||||
| #define COMPARE_OPT_OCTECT_STRING(ac,bc,e) \ | ||||
| @@ -73,6 +73,8 @@ static char *nada_tgt_principal[] = { "krbtgt", "NADA.KTH.SE" }; | ||||
| 	do { if (*(ac)->e != *(bc)->e) return 1; } while(0) | ||||
| #define COMPARE_MEM(ac,bc,e,len) \ | ||||
| 	do { if (memcmp((ac)->e, (bc)->e,len) != 0) return 1; } while(0) | ||||
| #define COMPARE_OCTECT_STRING(ac,bc,e) \ | ||||
| 	do { if ((ac)->e.length != (bc)->e.length || memcmp((ac)->e.data, (bc)->e.data, (ac)->e.length) != 0) return 1; } while(0) | ||||
|  | ||||
| static int | ||||
| cmp_principal (void *a, void *b) | ||||
| @@ -1407,6 +1409,178 @@ check_TESTMechTypeList(void) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| cmp_TESTSeqOf4(void *a, void *b) | ||||
| { | ||||
|     TESTSeqOf4 *aa = a; | ||||
|     TESTSeqOf4 *ab = b; | ||||
|     int i; | ||||
|  | ||||
|     IF_OPT_COMPARE(aa, ab, b1) { | ||||
| 	COMPARE_INTEGER(aa->b1, ab->b1, len); | ||||
| 	for (i = 0; i < aa->b1->len; ++i) { | ||||
| 	    COMPARE_INTEGER(aa->b1->val+i, ab->b1->val+i, u1); | ||||
| 	    COMPARE_INTEGER(aa->b1->val+i, ab->b1->val+i, u2); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b1->val+i, ab->b1->val+i, s1); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b1->val+i, ab->b1->val+i, s2); | ||||
| 	} | ||||
|     } | ||||
|     IF_OPT_COMPARE(aa, ab, b2) { | ||||
| 	COMPARE_INTEGER(aa->b2, ab->b2, len); | ||||
| 	for (i = 0; i < aa->b2->len; ++i) { | ||||
| 	    COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u1); | ||||
| 	    COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u2); | ||||
| 	    COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u3); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b2->val+i, ab->b2->val+i, s1); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b2->val+i, ab->b2->val+i, s2); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b2->val+i, ab->b2->val+i, s3); | ||||
| 	} | ||||
|     } | ||||
|     IF_OPT_COMPARE(aa, ab, b3) { | ||||
| 	COMPARE_INTEGER(aa->b3, ab->b3, len); | ||||
| 	for (i = 0; i < aa->b3->len; ++i) { | ||||
| 	    COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u1); | ||||
| 	    COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u2); | ||||
| 	    COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u3); | ||||
| 	    COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u4); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b3->val+i, ab->b3->val+i, s1); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b3->val+i, ab->b3->val+i, s2); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b3->val+i, ab->b3->val+i, s3); | ||||
| 	    COMPARE_OCTECT_STRING(aa->b3->val+i, ab->b3->val+i, s4); | ||||
| 	} | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| test_seq4 (void) | ||||
| { | ||||
|     struct test_case tests[] = { | ||||
| 	{ NULL,  2, | ||||
| 	  "\x30\x00", | ||||
| 	  "seq4 0" }, | ||||
| 	{ NULL,  4, | ||||
| 	  "\x30\x02" "\xa1\x00", | ||||
| 	  "seq4 1" }, | ||||
| 	{ NULL,  8, | ||||
| 	  "\x30\x06" "\xa0\x02\x30\x00" "\xa1\x00", | ||||
| 	  "seq4 2" }, | ||||
| 	{ NULL,  2 + (2 + 0x18) + (2 + 0x27) + (2 + 0x31), | ||||
| 	  "\x30\x76"					/* 2 SEQ */ | ||||
| 	   "\xa0\x18\x30\x16"				/* 4 [0] SEQ */ | ||||
| 	    "\x30\x14"					/* 2 SEQ */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
| 	   "\xa1\x27"					/* 2 [1] IMPL SEQ */ | ||||
| 	    "\x30\x25"					/* 2 SEQ */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
|              "\x04\x04\x00\x01\x02\x03"			/* 6 OCTET-STRING */ | ||||
| 	   "\xa2\x31"					/* 2 [2] IMPL SEQ */ | ||||
| 	    "\x30\x2f"					/* 2 SEQ */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
|              "\x04\x04\x00\x01\x02\x03"			/* 6 OCTET-STRING */ | ||||
| 	     "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x04\x01\x00"				/* 3 OCTET-STRING */ | ||||
| 	     "\x02\x05\x01\x00\x00\x00\x00",		/* 7 INT */ | ||||
| 	  "seq4 3" }, | ||||
|     }; | ||||
|  | ||||
|     int ret = 0, ntests = sizeof(tests) / sizeof(*tests); | ||||
|     TESTSeqOf4 c[4]; | ||||
|     struct TESTSeqOf4_b1 b1[4]; | ||||
|     struct TESTSeqOf4_b2 b2[4]; | ||||
|     struct TESTSeqOf4_b3 b3[4]; | ||||
|     struct TESTSeqOf4_b1_val b1val[4]; | ||||
|     struct TESTSeqOf4_b2_val b2val[4]; | ||||
|     struct TESTSeqOf4_b3_val b3val[4]; | ||||
|  | ||||
|     c[0].b1 = NULL; | ||||
|     c[0].b2 = NULL; | ||||
|     c[0].b3 = NULL; | ||||
|     tests[0].val = &c[0]; | ||||
|  | ||||
|     b2[1].len = 0; | ||||
|     b2[1].val = NULL; | ||||
|     c[1].b1 = NULL; | ||||
|     c[1].b2 = &b2[1]; | ||||
|     c[1].b3 = NULL; | ||||
|     tests[1].val = &c[1]; | ||||
|  | ||||
|     b1[2].len = 0; | ||||
|     b1[2].val = NULL; | ||||
|     b2[2].len = 0; | ||||
|     b2[2].val = NULL; | ||||
|     c[2].b1 = &b1[2]; | ||||
|     c[2].b2 = &b2[2]; | ||||
|     c[2].b3 = NULL; | ||||
|     tests[2].val = &c[2]; | ||||
|  | ||||
|     b1val[3].s1.data = ""; | ||||
|     b1val[3].s1.length = 0; | ||||
|     b1val[3].u1 = 1LL; | ||||
|     b1val[3].s2.data = "\x01\x02"; | ||||
|     b1val[3].s2.length = 2; | ||||
|     b1val[3].u2 = -1LL; | ||||
|  | ||||
|     b2val[3].s1.data = ""; | ||||
|     b2val[3].s1.length = 0; | ||||
|     b2val[3].u1 = 1LL; | ||||
|     b2val[3].s2.data = "\x01\x02"; | ||||
|     b2val[3].s2.length = 2; | ||||
|     b2val[3].u2 = -1LL; | ||||
|     b2val[3].s3.data = "\x00\x01\x02\x03"; | ||||
|     b2val[3].s3.length = 4; | ||||
|     b2val[3].u3 = 1LL<<63; | ||||
|  | ||||
|     b3val[3].s1.data = ""; | ||||
|     b3val[3].s1.length = 0; | ||||
|     b3val[3].u1 = 1LL; | ||||
|     b3val[3].s2.data = "\x01\x02"; | ||||
|     b3val[3].s2.length = 2; | ||||
|     b3val[3].u2 = -1LL; | ||||
|     b3val[3].s3.data = "\x00\x01\x02\x03"; | ||||
|     b3val[3].s3.length = 4; | ||||
|     b3val[3].u3 = 1LL<<63; | ||||
|     b3val[3].s4.data = "\x00"; | ||||
|     b3val[3].s4.length = 1; | ||||
|     b3val[3].u4 = 1LL<<32; | ||||
|  | ||||
|     b1[3].len = 1; | ||||
|     b1[3].val = &b1val[3]; | ||||
|     b2[3].len = 1; | ||||
|     b2[3].val = &b2val[3]; | ||||
|     b3[3].len = 1; | ||||
|     b3[3].val = &b3val[3]; | ||||
|     c[3].b1 = &b1[3]; | ||||
|     c[3].b2 = &b2[3]; | ||||
|     c[3].b3 = &b3[3]; | ||||
|     tests[3].val = &c[3]; | ||||
|  | ||||
|     ret += generic_test (tests, ntests, sizeof(TESTSeqOf4), | ||||
| 			 (generic_encode)encode_TESTSeqOf4, | ||||
| 			 (generic_length)length_TESTSeqOf4, | ||||
| 			 (generic_decode)decode_TESTSeqOf4, | ||||
| 			 (generic_free)free_TESTSeqOf4, | ||||
| 			 cmp_TESTSeqOf4, | ||||
| 			 (generic_copy)copy_TESTSeqOf4); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| { | ||||
| @@ -1439,6 +1613,7 @@ main(int argc, char **argv) | ||||
|     ret += check_seq_of_size(); | ||||
|  | ||||
|     ret += check_TESTMechTypeList(); | ||||
|     ret += test_seq4(); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|   | ||||
| @@ -278,6 +278,133 @@ test_seqof3(void) | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| test_seqof4(void) | ||||
| { | ||||
|     struct test_case tests[] = { | ||||
| 	{ NULL,  2, | ||||
| 	  "\x30\x00", | ||||
| 	  "seq4 0" }, | ||||
| 	{ NULL,  4, | ||||
| 	  "\x30\x02" "\xa1\x00", | ||||
| 	  "seq4 1" }, | ||||
| 	{ NULL,  8, | ||||
| 	  "\x30\x06" "\xa0\x02\x30\x00" "\xa1\x00", | ||||
| 	  "seq4 2" }, | ||||
| 	{ NULL,  2 + (2 + 0x18) + (2 + 0x27) + (2 + 0x31), | ||||
| 	  "\x30\x76"					/* 2 SEQ */ | ||||
| 	   "\xa0\x18\x30\x16"				/* 4 [0] SEQ */ | ||||
| 	    "\x30\x14"					/* 2 SEQ */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
| 	   "\xa1\x27"					/* 2 [1] IMPL SEQ */ | ||||
| 	    "\x30\x25"					/* 2 SEQ */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
|              "\x04\x04\x00\x01\x02\x03"			/* 6 OCTET-STRING */ | ||||
| 	   "\xa2\x31"					/* 2 [2] IMPL SEQ */ | ||||
| 	    "\x30\x2f"					/* 2 SEQ */ | ||||
| 	     "\x04\x00"					/* 2 OCTET-STRING */ | ||||
| 	     "\x02\x01\x01"				/* 3 INT */ | ||||
|              "\x04\x02\x01\x02"				/* 4 OCTET-STRING */ | ||||
| 	     "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff" | ||||
| 							/* 11 INT */ | ||||
|              "\x04\x04\x00\x01\x02\x03"			/* 6 OCTET-STRING */ | ||||
| 	     "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00" | ||||
| 							/* 11 INT */ | ||||
| 	     "\x04\x01\x00"				/* 3 OCTET-STRING */ | ||||
| 	     "\x02\x05\x01\x00\x00\x00\x00",		/* 7 INT */ | ||||
| 	  "seq4 3" }, | ||||
|     }; | ||||
|  | ||||
|     int ret = 0, ntests = sizeof(tests) / sizeof(*tests); | ||||
|     TESTSeqOf4 c[4]; | ||||
|     struct TESTSeqOf4_b1 b1[4]; | ||||
|     struct TESTSeqOf4_b2 b2[4]; | ||||
|     struct TESTSeqOf4_b3 b3[4]; | ||||
|     struct TESTSeqOf4_b1_val b1val[4]; | ||||
|     struct TESTSeqOf4_b2_val b2val[4]; | ||||
|     struct TESTSeqOf4_b3_val b3val[4]; | ||||
|  | ||||
|     c[0].b1 = NULL; | ||||
|     c[0].b2 = NULL; | ||||
|     c[0].b3 = NULL; | ||||
|     tests[0].val = &c[0]; | ||||
|  | ||||
|     b2[1].len = 0; | ||||
|     b2[1].val = NULL; | ||||
|     c[1].b1 = NULL; | ||||
|     c[1].b2 = &b2[1]; | ||||
|     c[1].b3 = NULL; | ||||
|     tests[1].val = &c[1]; | ||||
|  | ||||
|     b1[2].len = 0; | ||||
|     b1[2].val = NULL; | ||||
|     b2[2].len = 0; | ||||
|     b2[2].val = NULL; | ||||
|     c[2].b1 = &b1[2]; | ||||
|     c[2].b2 = &b2[2]; | ||||
|     c[2].b3 = NULL; | ||||
|     tests[2].val = &c[2]; | ||||
|  | ||||
|     b1val[3].s1.data = ""; | ||||
|     b1val[3].s1.length = 0; | ||||
|     b1val[3].u1 = 1LL; | ||||
|     b1val[3].s2.data = "\x01\x02"; | ||||
|     b1val[3].s2.length = 2; | ||||
|     b1val[3].u2 = -1LL; | ||||
|  | ||||
|     b2val[3].s1.data = ""; | ||||
|     b2val[3].s1.length = 0; | ||||
|     b2val[3].u1 = 1LL; | ||||
|     b2val[3].s2.data = "\x01\x02"; | ||||
|     b2val[3].s2.length = 2; | ||||
|     b2val[3].u2 = -1LL; | ||||
|     b2val[3].s3.data = "\x00\x01\x02\x03"; | ||||
|     b2val[3].s3.length = 4; | ||||
|     b2val[3].u3 = 1LL<<63; | ||||
|  | ||||
|     b3val[3].s1.data = ""; | ||||
|     b3val[3].s1.length = 0; | ||||
|     b3val[3].u1 = 1LL; | ||||
|     b3val[3].s2.data = "\x01\x02"; | ||||
|     b3val[3].s2.length = 2; | ||||
|     b3val[3].u2 = -1LL; | ||||
|     b3val[3].s3.data = "\x00\x01\x02\x03"; | ||||
|     b3val[3].s3.length = 4; | ||||
|     b3val[3].u3 = 1LL<<63; | ||||
|     b3val[3].s4.data = "\x00"; | ||||
|     b3val[3].s4.length = 1; | ||||
|     b3val[3].u4 = 1LL<<32; | ||||
|  | ||||
|     b1[3].len = 1; | ||||
|     b1[3].val = &b1val[3]; | ||||
|     b2[3].len = 1; | ||||
|     b2[3].val = &b2val[3]; | ||||
|     b3[3].len = 1; | ||||
|     b3[3].val = &b3val[3]; | ||||
|     c[3].b1 = &b1[3]; | ||||
|     c[3].b2 = &b2[3]; | ||||
|     c[3].b3 = &b3[3]; | ||||
|     tests[3].val = &c[3]; | ||||
|  | ||||
|     ret += generic_test (tests, ntests, sizeof(TESTSeqOf4), | ||||
| 			 (generic_encode)encode_TESTSeqOf4, | ||||
| 			 (generic_length)length_TESTSeqOf4, | ||||
| 			 (generic_decode)decode_TESTSeqOf4, | ||||
| 			 (generic_free)free_TESTSeqOf4, | ||||
| 			 cmp_dummy, | ||||
| 			 NULL); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| @@ -289,6 +416,7 @@ main(int argc, char **argv) | ||||
|     ret += test_seqofseq2(); | ||||
|     ret += test_seqof2(); | ||||
|     ret += test_seqof3(); | ||||
|     ret += test_seqof4(); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|   | ||||
| @@ -808,7 +808,9 @@ generate_template_type(const char *varname, | ||||
| { | ||||
|     struct tlist *tl; | ||||
|     const char *d; | ||||
|     char *szt = NULL; | ||||
|     int have_ellipsis = 0; | ||||
|     int n; | ||||
|  | ||||
|     tl = tlist_new(varname); | ||||
|  | ||||
| @@ -823,13 +825,24 @@ generate_template_type(const char *varname, | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     if (isstruct) | ||||
| 	if (name) | ||||
| 	    n = asprintf(&szt, "struct %s_%s", basetype, name); | ||||
| 	else | ||||
| 	    n = asprintf(&szt, "struct %s", basetype); | ||||
|     else | ||||
| 	n = asprintf(&szt, "%s", basetype); | ||||
|     if (n < 0 || szt == NULL) | ||||
| 	errx(1, "malloc"); | ||||
|  | ||||
|     if (ASN1_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull) | ||||
| 	errx(1, "Tag %s...%s with no content ?", basetype, name ? name : ""); | ||||
|  | ||||
|     tlist_header(tl, "{ 0%s%s, sizeof(%s%s), ((void *)%lu) }", | ||||
|     tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)%lu) }", | ||||
| 		 (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "", | ||||
| 		 have_ellipsis ? "|A1_HF_ELLIPSIS" : "", | ||||
| 		 isstruct ? "struct " : "", basetype, tlist_count(tl)); | ||||
| 		 have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl)); | ||||
|  | ||||
|     free(szt); | ||||
|  | ||||
|     d = tlist_find_dup(tl); | ||||
|     if (d) { | ||||
|   | ||||
| @@ -123,6 +123,36 @@ TESTSeqOf3 ::= SEQUENCE { | ||||
| 	strings SEQUENCE OF GeneralString OPTIONAL | ||||
| } | ||||
|  | ||||
| -- Larger/more complex to increase odds of out-of-bounds | ||||
| -- read/writes if miscoded | ||||
|  | ||||
| TESTSeqOf4 ::= SEQUENCE { | ||||
| 	b1 [0] SEQUENCE OF SEQUENCE { | ||||
| 		s1 OCTET STRING, | ||||
| 		s2 OCTET STRING, | ||||
| 		u1 TESTuint64, | ||||
| 		u2 TESTuint64 | ||||
| 	} OPTIONAL, | ||||
| 	b2 [1] IMPLICIT SEQUENCE OF SEQUENCE { | ||||
| 		u1 TESTuint64, | ||||
| 		u2 TESTuint64, | ||||
| 		u3 TESTuint64, | ||||
| 		s1 OCTET STRING, | ||||
| 		s2 OCTET STRING, | ||||
| 		s3 OCTET STRING | ||||
| 	} OPTIONAL, | ||||
| 	b3 [2] IMPLICIT SEQUENCE OF SEQUENCE { | ||||
| 		s1 OCTET STRING, | ||||
| 		u1 TESTuint64, | ||||
| 		s2 OCTET STRING, | ||||
| 		u2 TESTuint64, | ||||
| 		s3 OCTET STRING, | ||||
| 		u3 TESTuint64, | ||||
| 		s4 OCTET STRING, | ||||
| 		u4 TESTuint64 | ||||
| 	} OPTIONAL | ||||
| } | ||||
|  | ||||
| TESTPreserve ::= SEQUENCE { | ||||
| 	zero [0] TESTInteger, | ||||
| 	one [1] TESTInteger | ||||
|   | ||||
		Reference in New Issue
	
	Block a user