Sun Mar 28 19:53:58 2021 UTC ()
lint: add test for assertion failure in initialization

The 'cnt = level->bl_type->t_tspec == STRUCT ? 2 : 1;' in
initialization_push_struct_or_union is obviously wrong since not every
struct has exactly 1 remaining member after the first member that has an
initializer with designation.

This bug started its life in init.c 1.12 from 2002-10-21, a little over
18 years ago.


(rillig)
diff -r1.18 -r1.19 src/tests/usr.bin/xlint/lint1/d_c99_init.c
diff -r1.172 -r1.173 src/usr.bin/xlint/lint1/init.c

cvs diff -r1.18 -r1.19 src/tests/usr.bin/xlint/lint1/d_c99_init.c (expand / switch to unified diff)

--- src/tests/usr.bin/xlint/lint1/d_c99_init.c 2021/03/28 18:48:32 1.18
+++ src/tests/usr.bin/xlint/lint1/d_c99_init.c 2021/03/28 19:53:58 1.19
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: d_c99_init.c,v 1.18 2021/03/28 18:48:32 rillig Exp $ */ 1/* $NetBSD: d_c99_init.c,v 1.19 2021/03/28 19:53:58 rillig Exp $ */
2# 3 "d_c99_init.c" 2# 3 "d_c99_init.c"
3 3
4/* 4/*
5 * Test C99 initializers. 5 * Test C99 initializers.
6 * 6 *
7 * See C99 6.7.8 "Initialization". 7 * See C99 6.7.8 "Initialization".
8*/ 8*/
9 9
10 10
11void use(const void *); 11void use(const void *);
12 12
13typedef struct any { 13typedef struct any {
14 const void *value; 14 const void *value;
@@ -233,13 +233,34 @@ struct ends_with_unnamed_bit_field { @@ -233,13 +233,34 @@ struct ends_with_unnamed_bit_field {
233}; 233};
234 234
235char prefixed_message[] = { 235char prefixed_message[] = {
236 'E', ':', ' ', 236 'E', ':', ' ',
237 /* expect+1: illegal combination of integer (char) and pointer */ 237 /* expect+1: illegal combination of integer (char) and pointer */
238 "message\n", 238 "message\n",
239}; 239};
240 240
241char message_with_suffix[] = { 241char message_with_suffix[] = {
242 "message", 242 "message",
243 /* expect+1: too many array initializers */ 243 /* expect+1: too many array initializers */
244 '\n', 244 '\n',
245}; 245};
 246
 247struct ten {
 248 int i0;
 249 int i1;
 250 int i2;
 251 int i3;
 252 int i4;
 253 int i5;
 254 int i6;
 255 int i7;
 256 int i8;
 257 int i9;
 258};
 259
 260struct ten ten = {
 261 .i3 = 3,
 262 4,
 263 // FIXME: assertion "level->bl_type->t_tspec == ARRAY" failed in brace_level_extend_if_array_of_unknown_size
 264 // 5,
 265 // 6,
 266};

cvs diff -r1.172 -r1.173 src/usr.bin/xlint/lint1/init.c (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/init.c 2021/03/28 19:30:08 1.172
+++ src/usr.bin/xlint/lint1/init.c 2021/03/28 19:53:58 1.173
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: init.c,v 1.172 2021/03/28 19:30:08 rillig Exp $ */ 1/* $NetBSD: init.c,v 1.173 2021/03/28 19:53:58 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994, 1995 Jochen Pohl 4 * Copyright (c) 1994, 1995 Jochen Pohl
5 * All Rights Reserved. 5 * All Rights Reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#if HAVE_NBTOOL_CONFIG_H 34#if HAVE_NBTOOL_CONFIG_H
35#include "nbtool_config.h" 35#include "nbtool_config.h"
36#endif 36#endif
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39#if defined(__RCSID) && !defined(lint) 39#if defined(__RCSID) && !defined(lint)
40__RCSID("$NetBSD: init.c,v 1.172 2021/03/28 19:30:08 rillig Exp $"); 40__RCSID("$NetBSD: init.c,v 1.173 2021/03/28 19:53:58 rillig Exp $");
41#endif 41#endif
42 42
43#include <stdlib.h> 43#include <stdlib.h>
44#include <string.h> 44#include <string.h>
45 45
46#include "lint1.h" 46#include "lint1.h"
47 47
48 48
49/* 49/*
50 * Initialization 50 * Initialization
51 * 51 *
52 * Handles initializations of global or local objects, like in: 52 * Handles initializations of global or local objects, like in:
53 * 53 *
@@ -579,47 +579,47 @@ brace_level_look_up_member(const struct  @@ -579,47 +579,47 @@ brace_level_look_up_member(const struct
579 579
580 for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) { 580 for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) {
581 if (m->s_bitfield && m->s_name == unnamed) 581 if (m->s_bitfield && m->s_name == unnamed)
582 continue; 582 continue;
583 if (strcmp(m->s_name, name) == 0) 583 if (strcmp(m->s_name, name) == 0)
584 return m; 584 return m;
585 } 585 }
586 586
587 return NULL; 587 return NULL;
588} 588}
589 589
590/* TODO: merge duplicate code */ 590/* TODO: merge duplicate code */
591static sym_t * 591static sym_t *
592brace_level_look_up_member_named(struct brace_level *level, const char *name, 592brace_level_look_up_first_member_named(struct brace_level *level,
593 int *count) 593 const char *name, int *count)
594{ 594{
595 sym_t *m; 595 sym_t *m;
596 596
597 for (m = level->bl_type->t_str->sou_first_member; 597 for (m = level->bl_type->t_str->sou_first_member;
598 m != NULL; m = m->s_next) { 598 m != NULL; m = m->s_next) {
599 if (m->s_bitfield && m->s_name == unnamed) 599 if (m->s_bitfield && m->s_name == unnamed)
600 continue; 600 continue;
601 if (strcmp(m->s_name, name) != 0) 601 if (strcmp(m->s_name, name) != 0)
602 continue; 602 continue;
603 (*count)++; 603 (*count)++;
604 break; 604 break;
605 } 605 }
606 606
607 return m; 607 return m;
608} 608}
609 609
610/* TODO: merge duplicate code */ 610/* TODO: merge duplicate code */
611static sym_t * 611static sym_t *
612brace_level_look_up_member_unnamed(struct brace_level *level, int *count) 612brace_level_look_up_first_member_unnamed(struct brace_level *level, int *count)
613{ 613{
614 sym_t *m; 614 sym_t *m;
615 615
616 for (m = level->bl_type->t_str->sou_first_member; 616 for (m = level->bl_type->t_str->sou_first_member;
617 m != NULL; m = m->s_next) { 617 m != NULL; m = m->s_next) {
618 if (m->s_bitfield && m->s_name == unnamed) 618 if (m->s_bitfield && m->s_name == unnamed)
619 continue; 619 continue;
620 /* XXX: What is this code for? */ 620 /* XXX: What is this code for? */
621 if (++(*count) == 1) { 621 if (++(*count) == 1) {
622 level->bl_next_member = m; 622 level->bl_next_member = m;
623 level->bl_subtype = m->s_type; 623 level->bl_subtype = m->s_type;
624 } 624 }
625 } 625 }
@@ -820,30 +820,30 @@ initialization_push_struct_or_union(stru @@ -820,30 +820,30 @@ initialization_push_struct_or_union(stru
820 /* initialization of an incomplete type */ 820 /* initialization of an incomplete type */
821 error(175); 821 error(175);
822 initialization_set_error(in); 822 initialization_set_error(in);
823 return false; 823 return false;
824 } 824 }
825 825
826 cnt = 0; 826 cnt = 0;
827 designation_debug(&in->designation); 827 designation_debug(&in->designation);
828 debug_step("lookup for '%s'%s", 828 debug_step("lookup for '%s'%s",
829 type_name(level->bl_type), 829 type_name(level->bl_type),
830 level->bl_seen_named_member ? ", seen named member" : ""); 830 level->bl_seen_named_member ? ", seen named member" : "");
831 831
832 if (in->designation.head != NULL) 832 if (in->designation.head != NULL)
833 m = brace_level_look_up_member_named(level, 833 m = brace_level_look_up_first_member_named(level,
834 in->designation.head->name, &cnt); 834 in->designation.head->name, &cnt);
835 else 835 else
836 m = brace_level_look_up_member_unnamed(level, &cnt); 836 m = brace_level_look_up_first_member_unnamed(level, &cnt);
837 837
838 if (in->designation.head != NULL) { 838 if (in->designation.head != NULL) {
839 if (m == NULL) { 839 if (m == NULL) {
840 debug_step("pop struct"); 840 debug_step("pop struct");
841 return true; 841 return true;
842 } 842 }
843 level->bl_next_member = m; 843 level->bl_next_member = m;
844 level->bl_subtype = m->s_type; 844 level->bl_subtype = m->s_type;
845 level->bl_seen_named_member = true; 845 level->bl_seen_named_member = true;
846 debug_step("named member '%s'", 846 debug_step("named member '%s'",
847 in->designation.head->name); 847 in->designation.head->name);
848 designation_shift_level(&in->designation); 848 designation_shift_level(&in->designation);
849 cnt = level->bl_type->t_tspec == STRUCT ? 2 : 1; 849 cnt = level->bl_type->t_tspec == STRUCT ? 2 : 1;