More file name and mode checks for $fopen{a,r,w}?.
This patch adds checks that $fopen is only called with a valid
mode argument. It also checks that the file name for $fopen{a,r,w}?
is a valid looking file name (all characters satisfy isprint()).
The later should prevent creating weird file names because of
Verilog bugs.
This commit is contained in:
parent
6321fb6a92
commit
f6edd098a9
|
|
@ -20,6 +20,7 @@
|
|||
# include "vpi_user.h"
|
||||
# include "sys_priv.h"
|
||||
# include <assert.h>
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
|
@ -91,6 +92,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
s_vpi_value val;
|
||||
int fail = 0;
|
||||
char *mode_string = 0;
|
||||
unsigned idx;
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
vpiHandle mode = vpi_scan(argv);
|
||||
|
||||
|
|
@ -103,10 +105,54 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument was not a valid string.\n",
|
||||
vpi_printf("%s's mode argument is not a valid string.\n",
|
||||
name);
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
/* Make sure the mode string is correct. */
|
||||
if (strlen(val.value.str) > 3) {
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is too long.\n",
|
||||
name, val.value.str);
|
||||
fail = 1;
|
||||
} else {
|
||||
unsigned bin = 0, plus = 0;
|
||||
switch (val.value.str[0]) {
|
||||
case 'r':
|
||||
case 'w':
|
||||
case 'a':
|
||||
for (idx = 1; idx < 3 ; idx++) {
|
||||
if (val.value.str[idx] == '\0') break;
|
||||
switch (val.value.str[idx]) {
|
||||
case 'b':
|
||||
if (bin) fail = 1;
|
||||
bin = 1;
|
||||
break;
|
||||
case '+':
|
||||
if (plus) fail = 1;
|
||||
plus = 1;
|
||||
break;
|
||||
default:
|
||||
fail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! fail) break;
|
||||
|
||||
default:
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is invalid.\n",
|
||||
name, val.value.str);
|
||||
fail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mode_string = strdup(val.value.str);
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
|
@ -121,12 +167,31 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument was not a valid string.\n",
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
fail = 1;
|
||||
if (mode) free(mode_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the file name is composed of only printable
|
||||
* characters.
|
||||
*/
|
||||
unsigned len = strlen(val.value.str);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
"printable characters.\n", msg, name);
|
||||
vpi_printf("%*s \"%s\"\n", strlen(msg), " ", val.value.str);
|
||||
fail = 1;
|
||||
if (mode) free(mode_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* If either the mode or file name are not valid just return. */
|
||||
if (fail) return 0;
|
||||
|
||||
|
|
@ -168,11 +233,29 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
|||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument was not a valid string.\n",
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the file name is composed of only printable
|
||||
* characters.
|
||||
*/
|
||||
unsigned idx, len = strlen(val.value.str);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
"printable characters.\n", msg, name);
|
||||
vpi_printf("%*s \"%s\"\n", strlen(msg), " ", val.value.str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the file and return the result. */
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = vpi_fopen(val.value.str, mode);
|
||||
|
|
@ -616,19 +699,19 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
|||
|
||||
val.format = vpiIntVal;
|
||||
switch (name[4]) {
|
||||
case 'l': /* $ftell() */
|
||||
case 'l': /* $ftell() */
|
||||
val.value.integer = ftell(fp);
|
||||
break;
|
||||
case 'f': /* $feof() is from 1264-2005*/
|
||||
case 'f': /* $feof() is from 1264-2005*/
|
||||
val.value.integer = feof(fp);
|
||||
break;
|
||||
case 'i': /* $rewind() */
|
||||
case 'i': /* $rewind() */
|
||||
val.value.integer = fseek(fp, 0L, SEEK_SET);
|
||||
break;
|
||||
case 't': /* $fgetc() */
|
||||
case 't': /* $fgetc() */
|
||||
val.value.integer = fgetc(fp);
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s cannot be processed with this routine.\n", name);
|
||||
|
|
|
|||
Loading…
Reference in New Issue