Skip to content

Commit e7c9540

Browse files
committed
Add optional index check
1 parent 0cc8207 commit e7c9540

File tree

9 files changed

+379
-14
lines changed

9 files changed

+379
-14
lines changed

cobc/codegen.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7675,10 +7675,38 @@ static void
76757675
output_perform_until (struct cb_perform *p, cb_tree l)
76767676
{
76777677
struct cb_perform_varying *v;
7678-
struct cb_field *f;
76797678
cb_tree next;
76807679

76817680
if (l == NULL) {
7681+
if (cb_flag_check_subscript_set
7682+
&& CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) {
7683+
cb_tree xn;
7684+
/* Check all INDEXED BY variables used in VARYING */
7685+
for (xn = p->varying; xn; xn = CB_CHAIN (xn)) {
7686+
v = CB_PERFORM_VARYING (CB_VALUE (xn));
7687+
if (v->name
7688+
&& CB_REF_OR_FIELD_P (v->name)) {
7689+
struct cb_field *f = CB_FIELD_PTR (v->name);
7690+
if (f->flag_indexed_by
7691+
&& f->index_qual) {
7692+
f = f->index_qual;
7693+
output_prefix ();
7694+
output ("cob_check_subscript (");
7695+
output_integer (v->name);
7696+
output (", ");
7697+
if (f->depending) {
7698+
output_integer (f->depending);
7699+
output (", \"%s\", 1", f->name);
7700+
} else {
7701+
output ("%d, \"%s\", 0", f->occurs_max, f->name);
7702+
}
7703+
output (");");
7704+
output_newline ();
7705+
}
7706+
}
7707+
}
7708+
}
7709+
76827710
/* Perform body at the end */
76837711
output_perform_once (p);
76847712
return;
@@ -7695,7 +7723,7 @@ output_perform_until (struct cb_perform *p, cb_tree l)
76957723
CB_PERFORM_VARYING (CB_VALUE (next))->name);
76967724
/* DEBUG */
76977725
if (current_prog->flag_gen_debug) {
7698-
f = CB_FIELD (cb_ref (CB_PERFORM_VARYING (CB_VALUE (next))->name));
7726+
struct cb_field *f = CB_FIELD (cb_ref (CB_PERFORM_VARYING (CB_VALUE (next))->name));
76997727
if (f->flag_field_debug) {
77007728
output_stmt (cb_build_debug (cb_debug_name,
77017729
(const char *)f->name, NULL));

cobc/flag.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ CB_FLAG (cb_flag_stack_check, 1, "stack-check",
186186
_(" -fstack-check PERFORM stack checking\n"
187187
" * turned on by --debug/-g"))
188188

189+
CB_FLAG (cb_flag_check_subscript_set, 1, "opt-check-subscript-set",
190+
_(" -fopt-check-subscript-set check subscript in PERFORM/SET"))
191+
189192
CB_FLAG_OP (1, "memory-check", CB_FLAG_GETOPT_MEMORY_CHECK,
190193
_(" -fmemory-check=<scope> checks for invalid writes to internal storage,\n"
191194
" <scope> may be one of: all, pointer, using, none\n"

cobc/parser.y

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16476,7 +16476,7 @@ set_to:
1647616476
{
1647716477
cb_emit_set_to_fcdkey ($1, $7);
1647816478
}
16479-
| target_x_list TO x
16479+
| target_x_list TO x_numeric_or_pointer
1648016480
{
1648116481
cb_emit_set_to ($1, $3);
1648216482
}
@@ -16486,6 +16486,51 @@ set_to:
1648616486
}
1648716487
;
1648816488

16489+
x_numeric_or_pointer:
16490+
identifier
16491+
{
16492+
switch (cb_tree_class ($1)) {
16493+
case CB_CLASS_INDEX:
16494+
case CB_CLASS_POINTER:
16495+
case CB_CLASS_NUMERIC:
16496+
$$ = $1;
16497+
break;
16498+
default:
16499+
if ($1 != cb_error_node) {
16500+
cb_error_x ($1, _("an integer, INDEX, or a POINTER is expected here"));
16501+
}
16502+
$$ = cb_error_node;
16503+
}
16504+
}
16505+
| literal
16506+
{
16507+
switch (cb_tree_class ($1)) {
16508+
case CB_CLASS_INDEX:
16509+
case CB_CLASS_POINTER:
16510+
case CB_CLASS_NUMERIC:
16511+
if (!(CB_NUMERIC_LITERAL_P ($1)
16512+
&& (CB_LITERAL ($1))->scale != 0)) {
16513+
$$ = $1;
16514+
break;
16515+
}
16516+
/* fall through */
16517+
default:
16518+
if ($1 != cb_error_node) {
16519+
cb_error_x ($1, _("an integer, INDEX, or a POINTER is expected here"));
16520+
}
16521+
$$ = cb_error_node;
16522+
}
16523+
}
16524+
| ADDRESS _of prog_or_entry alnum_or_id
16525+
{
16526+
$$ = cb_build_ppointer ($4);
16527+
}
16528+
| ADDRESS _of identifier_1
16529+
{
16530+
$$ = cb_build_address (check_not_88_level ($3));
16531+
}
16532+
;
16533+
1648916534
/* SET name ... UP/DOWN BY expr */
1649016535

1649116536
set_up_down:

cobc/typeck.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13737,10 +13737,49 @@ cb_check_set_to (cb_tree vars, cb_tree x, const int emit_error)
1373713737
return error_found;
1373813738
}
1373913739

13740+
void
13741+
cb_emit_check_index (cb_tree vars, int hasval, int setval)
13742+
{
13743+
cb_tree l, v;
13744+
struct cb_field *f, *p;
13745+
for (l = vars; l; l = CB_CHAIN (l)) {
13746+
v = CB_VALUE (l);
13747+
if (!CB_REF_OR_FIELD_P (v)) continue;
13748+
f = CB_FIELD_PTR (v);
13749+
if (!f->flag_indexed_by) continue;
13750+
if (!f->index_qual) continue;
13751+
p = f->index_qual;
13752+
if (p->depending) {
13753+
if (hasval) {
13754+
if (setval > p->occurs_max
13755+
|| setval < p->occurs_min) {
13756+
cb_warning_x (COBC_WARN_FILLER, l,
13757+
_("SET %s TO %d is out of bounds"),
13758+
f->name, setval);
13759+
cb_emit (CB_BUILD_FUNCALL_1 ("cob_set_exception",
13760+
cb_int (COB_EC_RANGE_INDEX)));
13761+
}
13762+
if (setval >= p->occurs_min) continue;
13763+
}
13764+
} else
13765+
if (hasval
13766+
&& setval >= p->occurs_min
13767+
&& setval <= p->occurs_max) {
13768+
continue; /* Checks OK at compile time */
13769+
} else {
13770+
if (hasval) {
13771+
cb_warning_x (COBC_WARN_FILLER, l,
13772+
_("SET %s TO %d is out of bounds"), f->name, setval);
13773+
}
13774+
}
13775+
}
13776+
}
13777+
1374013778
void
1374113779
cb_emit_set_to (cb_tree vars, cb_tree src)
1374213780
{
1374313781
cb_tree l;
13782+
int hasval, setval;
1374413783

1374513784
/* Emit statements only if targets have the correct class. */
1374613785
if (cb_check_set_to (vars, src, 1)) {
@@ -13757,6 +13796,20 @@ cb_emit_set_to (cb_tree vars, cb_tree src)
1375713796
for (l = vars; l; l = CB_CHAIN (l)) {
1375813797
cb_emit (cb_build_move (src, CB_VALUE (l)));
1375913798
}
13799+
13800+
hasval = setval = 0;
13801+
if (CB_LITERAL_P (src)) {
13802+
if (CB_NUMERIC_LITERAL_P (src)) {
13803+
setval = cb_get_int (src);
13804+
hasval = 1;
13805+
}
13806+
} else if (src == cb_zero) {
13807+
hasval = 1;
13808+
}
13809+
if (cb_flag_check_subscript_set
13810+
&& CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) {
13811+
cb_emit_check_index (vars, hasval, setval);
13812+
}
1376013813
}
1376113814

1376213815
/*
@@ -13898,6 +13951,7 @@ cb_emit_set_to_fcdkey (cb_tree vars, cb_tree x)
1389813951
void
1389913952
cb_emit_set_up_down (cb_tree l, cb_tree flag, cb_tree x)
1390013953
{
13954+
cb_tree vars = l;
1390113955
if (cb_validate_one (x)
1390213956
|| cb_validate_list (l)) {
1390313957
return;
@@ -13910,6 +13964,9 @@ cb_emit_set_up_down (cb_tree l, cb_tree flag, cb_tree x)
1391013964
cb_emit (cb_build_sub (target, x, cb_int0));
1391113965
}
1391213966
}
13967+
if (CB_EXCEPTION_ENABLE (COB_EC_RANGE_INDEX)) {
13968+
cb_emit_check_index (vars, 0, 0);
13969+
}
1391313970
}
1391413971

1391513972
void

tests/testsuite.src/run_misc.at

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,9 @@ AT_DATA([prog.cob], [
707707
STOP RUN.
708708
])
709709

710-
AT_CHECK([$COMPILE prog.cob], [0], [], [])
710+
AT_CHECK([$COMPILE -fopt-check-subscript-set prog.cob], [0], [],
711+
[prog.cob:9: warning: SET I TO 0 is out of bounds
712+
])
711713
AT_CHECK([$COBCRUN_DIRECT ./prog], [0], [], [])
712714

713715
AT_CLEANUP
@@ -3978,7 +3980,7 @@ AT_DATA([prog.cob], [
39783980
01 KK PIC X.
39793981
PROCEDURE DIVISION.
39803982
SORT TBL ASCENDING KEY K.
3981-
SET KK TO "3"
3983+
MOVE "3" TO KK
39823984
SEARCH ALL TBL
39833985
AT END
39843986
DISPLAY KK " NOT FOUND"

tests/testsuite.src/run_subscripts.at

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,121 @@ AT_CHECK([$COMPILE prog.cob], [0], [], [])
582582
AT_CHECK([$COBCRUN_DIRECT ./prog], [0], [Hi, there!])
583583

584584
AT_CLEANUP
585+
586+
587+
AT_SETUP([Check Subscripts])
588+
AT_KEYWORDS([SUBSCRIPT])
589+
590+
AT_DATA([prog.cob], [
591+
IDENTIFICATION DIVISION.
592+
PROGRAM-ID. prog.
593+
DATA DIVISION.
594+
WORKING-STORAGE SECTION.
595+
01 BINB PIC 9(9) COMP-5 VALUE 42.
596+
01 NIDX PIC S99.
597+
01 MYIDX USAGE IS INDEX.
598+
01 MAXIDX PIC 9999 VALUE 3 COMP-5.
599+
01 TBL.
600+
05 FILLER PIC X(8) VALUE "Fred".
601+
05 FILLER PIC X(8) VALUE "Barney".
602+
05 FILLER PIC X(8) VALUE "Wilma".
603+
05 FILLER PIC X(8) VALUE "Betty".
604+
01 FILLER REDEFINES TBL.
605+
05 MYNAME PIC X(8) OCCURS 4 INDEXED BY IB1.
606+
01 TBL2.
607+
05 MYMRK PIC X(3)
608+
OCCURS 2 TO 5 DEPENDING ON MAXIDX
609+
INDEXED BY IB2.
610+
PROCEDURE DIVISION.
611+
MOVE 5 TO MAXIDX
612+
SET NIDX TO IB1.
613+
DISPLAY "Initial value: " NIDX.
614+
SET IB2 TO 10.
615+
MOVE "A:" TO MYMRK (1)
616+
MOVE "B:" TO MYMRK (2)
617+
MOVE "C:" TO MYMRK (3)
618+
MOVE "D:" TO MYMRK (4)
619+
MOVE "E:" TO MYMRK (5)
620+
MOVE 3 TO MAXIDX.
621+
CALL "SUBN" USING BY VALUE BINB.
622+
SET IB1 TO 2.
623+
* MF: Passing INDEX as CALL parameter is an error
624+
* CALL "SUBN" USING BY VALUE IB1.
625+
626+
* MF: Passing INDEX as DISPLAY parameter is an error
627+
* SET MYIDX TO IB1
628+
* DISPLAY MYIDX
629+
630+
SET MYIDX TO IB1.
631+
CALL "SUBN" USING BY VALUE MYIDX.
632+
SET IB1 TO 1.
633+
SET MYIDX TO IB1.
634+
CALL "SUBN" USING BY VALUE MYIDX.
635+
SET IB1, IB2 TO 4.
636+
SET IB2 TO MAXIDX.
637+
SET IB1, IB2 UP BY 1.
638+
SET IB1 TO 3.
639+
SET MYIDX TO IB1.
640+
CALL "SUBN" USING BY VALUE MYIDX.
641+
MOVE -1 TO NIDX
642+
SET IB1 TO NIDX.
643+
SET IB1 TO -9.
644+
SET IB1 TO 300.
645+
MOVE 400 TO IB1.
646+
* MOVE -1 TO NIDX
647+
* DISPLAY NIDX ": " MYNAME (NIDX) " ... The Begin!".
648+
PERFORM VARYING IB1 FROM 1 BY 1 UNTIL IB1 > MAXIDX
649+
SET IB2 TO IB1
650+
SET NIDX TO IB1
651+
SET MYIDX TO IB1
652+
DISPLAY NIDX ": " MYMRK (IB2) MYNAME (IB1) "."
653+
IF MYNAME (NIDX) = "Fred"
654+
MOVE "Freddy" TO MYNAME (NIDX)
655+
END-IF
656+
END-PERFORM.
657+
* SET NIDX TO IB1
658+
* DISPLAY NIDX ": " MYNAME (IB1) " ... The End!".
659+
660+
PERFORM VARYING IB2 FROM 1 BY 1 UNTIL IB2 > 4
661+
SET IB1 TO IB2
662+
* MF: Using wrong INDEX is warning and does not work
663+
* DISPLAY MYMRK (IB1) MYNAME (IB1)
664+
665+
SET NIDX TO IB1
666+
SET MYIDX TO IB1
667+
DISPLAY NIDX ": " MYMRK (IB2) MYNAME (IB1) "."
668+
IF MYNAME (IB1) = "Fred"
669+
MOVE "Freddy" TO MYNAME (IB1)
670+
END-IF
671+
END-PERFORM.
672+
STOP RUN.
673+
END PROGRAM prog.
674+
675+
IDENTIFICATION DIVISION.
676+
PROGRAM-ID. SUBN.
677+
DATA DIVISION.
678+
LINKAGE SECTION.
679+
01 n PIC S9(9) COMP-5.
680+
PROCEDURE DIVISION USING BY VALUE n.
681+
DISPLAY 'Number is ' n.
682+
END PROGRAM SUBN.
683+
])
684+
685+
AT_CHECK([$COMPILE -fopt-check-subscript-set -Wno-unfinished -Wno-others prog.cob], [0], [], [])
686+
AT_CHECK([$COBCRUN_DIRECT ./prog], [1], [Initial value: +01
687+
Number is +0000000042
688+
Number is +0000000002
689+
Number is +0000000001
690+
Number is +0000000003
691+
+01: A: Fred .
692+
+02: B: Barney .
693+
+03: C: Wilma .
694+
+01: A: Freddy .
695+
+02: B: Barney .
696+
+03: C: Wilma .
697+
], [libcob: prog.cob:71: error: subscript of 'MYMRK' out of bounds: 4
698+
note: current maximum subscript for 'MYMRK': 3
699+
])
700+
701+
AT_CLEANUP
702+

tests/testsuite.src/syn_misc.at

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6124,7 +6124,7 @@ prog.cob:27: error: condition-name not allowed here: 'val-i1'
61246124
prog.cob:29: error: condition-name not allowed here: 'vnum-1'
61256125
prog.cob:30: error: condition-name not allowed here: 'vnum-1'
61266126
prog.cob:31: error: condition-name not allowed here: 'vnum-2'
6127-
prog.cob:33: error: condition-name not allowed here: 'val-i1'
6127+
prog.cob:33: error: an integer, INDEX, or a POINTER is expected here
61286128
prog.cob:34: error: condition-name not allowed here: 'val-i2'
61296129
prog.cob:32: error: 'val-i1 (MAIN SECTION:)' is not a procedure name
61306130
])

0 commit comments

Comments
 (0)