Skip to content

Commit 02e51ce

Browse files
committed
Add optional index check
1 parent a23f0dc commit 02e51ce

File tree

5 files changed

+219
-1
lines changed

5 files changed

+219
-1
lines changed

cobc/codegen.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7670,6 +7670,33 @@ output_perform_until (struct cb_perform *p, cb_tree l)
76707670
cb_tree next;
76717671

76727672
if (l == NULL) {
7673+
if (cb_flag_check_subscript_set
7674+
&& CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) {
7675+
cb_tree xn;
7676+
/* Check all INDEXED BY variables used in VARYING */
7677+
for (xn = p->varying; xn; xn = CB_CHAIN (xn)) {
7678+
struct cb_field *q;
7679+
v = CB_PERFORM_VARYING (CB_VALUE (xn));
7680+
if (!v->name) continue;
7681+
f = CB_FIELD_PTR (v->name);
7682+
if (!f->flag_indexed_by) continue;
7683+
if (!f->index_qual) continue;
7684+
q = f->index_qual;
7685+
output_prefix ();
7686+
output ("cob_check_subscript (");
7687+
output_integer (CB_PERFORM_VARYING(CB_VALUE (xn))->name);
7688+
output (", ");
7689+
if (q->depending) {
7690+
output_integer (q->depending);
7691+
output (", \"%s\", 1", q->name);
7692+
} else {
7693+
output ("%d, \"%s\", 0", q->occurs_max, q->name);
7694+
}
7695+
output (");");
7696+
output_newline ();
7697+
}
7698+
}
7699+
76737700
/* Perform body at the end */
76747701
output_perform_once (p);
76757702
return;

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/typeck.c

Lines changed: 60 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,23 @@ 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+
if (CB_LITERAL (src)->scale != 0) {
13804+
cb_warning_x (COBC_WARN_FILLER, src, _("SET TO should be an integer"));
13805+
}
13806+
setval = cb_get_int (src);
13807+
hasval = 1;
13808+
}
13809+
} else if (src == cb_zero) {
13810+
hasval = 1;
13811+
}
13812+
if (cb_flag_check_subscript_set
13813+
&& CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) {
13814+
cb_emit_check_index (vars, hasval, setval);
13815+
}
1376013816
}
1376113817

1376213818
/*
@@ -13898,6 +13954,7 @@ cb_emit_set_to_fcdkey (cb_tree vars, cb_tree x)
1389813954
void
1389913955
cb_emit_set_up_down (cb_tree l, cb_tree flag, cb_tree x)
1390013956
{
13957+
cb_tree vars = l;
1390113958
if (cb_validate_one (x)
1390213959
|| cb_validate_list (l)) {
1390313960
return;
@@ -13910,6 +13967,9 @@ cb_emit_set_up_down (cb_tree l, cb_tree flag, cb_tree x)
1391013967
cb_emit (cb_build_sub (target, x, cb_int0));
1391113968
}
1391213969
}
13970+
if (CB_EXCEPTION_ENABLE (COB_EC_RANGE_INDEX)) {
13971+
cb_emit_check_index (vars, 0, 0);
13972+
}
1391313973
}
1391413974

1391513975
void

tests/testsuite.src/run_misc.at

Lines changed: 3 additions & 1 deletion
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

tests/testsuite.src/run_subscripts.at

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,129 @@ 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 0.2.
615+
SET IB2 TO "fred".
616+
SET IB2 TO 10.
617+
MOVE "A:" TO MYMRK (1)
618+
MOVE "B:" TO MYMRK (2)
619+
MOVE "C:" TO MYMRK (3)
620+
MOVE "D:" TO MYMRK (4)
621+
MOVE "E:" TO MYMRK (5)
622+
MOVE 3 TO MAXIDX.
623+
CALL "SUBN" USING BY VALUE BINB.
624+
SET IB1 TO 2.
625+
* MF: Passing INDEX as CALL parameter is an error
626+
* CALL "SUBN" USING BY VALUE IB1.
627+
628+
* MF: Passing INDEX as DISPLAY parameter is an error
629+
* SET MYIDX TO IB1
630+
* DISPLAY MYIDX
631+
632+
SET MYIDX TO IB1.
633+
CALL "SUBN" USING BY VALUE MYIDX.
634+
SET IB1 TO 1.
635+
SET MYIDX TO IB1.
636+
CALL "SUBN" USING BY VALUE MYIDX.
637+
SET IB1, IB2 TO 4.
638+
SET IB2 TO MAXIDX.
639+
SET IB1, IB2 UP BY 1.
640+
SET IB1 TO 3.
641+
SET MYIDX TO IB1.
642+
CALL "SUBN" USING BY VALUE MYIDX.
643+
MOVE -1 TO NIDX
644+
SET IB1 TO NIDX.
645+
SET IB1 TO -9.
646+
SET IB1 TO 300.
647+
MOVE 400 TO IB1.
648+
* MOVE -1 TO NIDX
649+
* DISPLAY NIDX ": " MYNAME (NIDX) " ... The Begin!".
650+
PERFORM VARYING IB1 FROM 1 BY 1 UNTIL IB1 > MAXIDX
651+
SET IB2 TO IB1
652+
SET NIDX TO IB1
653+
SET MYIDX TO IB1
654+
DISPLAY NIDX ": " MYMRK (IB2) MYNAME (IB1) "."
655+
IF MYNAME (NIDX) = "Fred"
656+
MOVE "Freddy" TO MYNAME (NIDX)
657+
END-IF
658+
END-PERFORM.
659+
* SET NIDX TO IB1
660+
* DISPLAY NIDX ": " MYNAME (IB1) " ... The End!".
661+
662+
PERFORM VARYING IB2 FROM 1 BY 1 UNTIL IB2 > 4
663+
SET IB1 TO IB2
664+
* MF: Using wrong INDEX is warning and does not work
665+
* DISPLAY MYMRK (IB1) MYNAME (IB1)
666+
667+
SET NIDX TO IB1
668+
SET MYIDX TO IB1
669+
DISPLAY NIDX ": " MYMRK (IB2) MYNAME (IB1) "."
670+
IF MYNAME (IB1) = "Fred"
671+
MOVE "Freddy" TO MYNAME (IB1)
672+
END-IF
673+
END-PERFORM.
674+
STOP RUN.
675+
END PROGRAM prog.
676+
677+
IDENTIFICATION DIVISION.
678+
PROGRAM-ID. SUBN.
679+
DATA DIVISION.
680+
LINKAGE SECTION.
681+
01 n PIC S9(9) COMP-5.
682+
PROCEDURE DIVISION USING BY VALUE n.
683+
DISPLAY 'Number is ' n.
684+
END PROGRAM SUBN.
685+
])
686+
687+
AT_CHECK([$COMPILE -x -std=mf -debug -Wall -Wno-unfinished -debug -fopt-check-subscript-set -fdefaultbyte=init -O prog.cob ], [0], [], [prog.cob:25: warning: SET TO should be an integer
688+
prog.cob:26: warning: source is non-numeric - substituting zero
689+
prog.cob:27: warning: SET IB2 TO 10 is out of bounds
690+
prog.cob:56: warning: SET IB1 TO -9 is out of bounds
691+
prog.cob:57: warning: SET IB1 TO 300 is out of bounds
692+
])
693+
694+
AT_CHECK([$COBCRUN_DIRECT ./prog], [1], [Initial value: +01
695+
Number is +0000000042
696+
Number is +0000000002
697+
Number is +0000000001
698+
Number is +0000000003
699+
+01: A: Fred .
700+
+02: B: Barney .
701+
+03: C: Wilma .
702+
+01: A: Freddy .
703+
+02: B: Barney .
704+
+03: C: Wilma .
705+
], [libcob: prog.cob:73: error: subscript of 'MYMRK' out of bounds: 4
706+
note: current maximum subscript for 'MYMRK': 3
707+
])
708+
709+
AT_CLEANUP
710+

0 commit comments

Comments
 (0)