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 "vpi_user.h"
|
||||||
# include "sys_priv.h"
|
# include "sys_priv.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
# include <ctype.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
@ -91,6 +92,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
char *mode_string = 0;
|
char *mode_string = 0;
|
||||||
|
unsigned idx;
|
||||||
vpiHandle item = vpi_scan(argv);
|
vpiHandle item = vpi_scan(argv);
|
||||||
vpiHandle mode = 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_printf("WARNING: %s line %d: ",
|
||||||
vpi_get_str(vpiFile, callh),
|
vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, 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);
|
name);
|
||||||
fail = 1;
|
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);
|
mode_string = strdup(val.value.str);
|
||||||
|
|
||||||
vpi_free_object(argv);
|
vpi_free_object(argv);
|
||||||
|
|
@ -121,12 +167,31 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
||||||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, 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);
|
name);
|
||||||
fail = 1;
|
fail = 1;
|
||||||
if (mode) free(mode_string);
|
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 either the mode or file name are not valid just return. */
|
||||||
if (fail) return 0;
|
if (fail) return 0;
|
||||||
|
|
||||||
|
|
@ -168,11 +233,29 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
||||||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, 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);
|
name);
|
||||||
return 0;
|
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. */
|
/* Open the file and return the result. */
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = vpi_fopen(val.value.str, mode);
|
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;
|
val.format = vpiIntVal;
|
||||||
switch (name[4]) {
|
switch (name[4]) {
|
||||||
case 'l': /* $ftell() */
|
case 'l': /* $ftell() */
|
||||||
val.value.integer = ftell(fp);
|
val.value.integer = ftell(fp);
|
||||||
break;
|
break;
|
||||||
case 'f': /* $feof() is from 1264-2005*/
|
case 'f': /* $feof() is from 1264-2005*/
|
||||||
val.value.integer = feof(fp);
|
val.value.integer = feof(fp);
|
||||||
break;
|
break;
|
||||||
case 'i': /* $rewind() */
|
case 'i': /* $rewind() */
|
||||||
val.value.integer = fseek(fp, 0L, SEEK_SET);
|
val.value.integer = fseek(fp, 0L, SEEK_SET);
|
||||||
break;
|
break;
|
||||||
case 't': /* $fgetc() */
|
case 't': /* $fgetc() */
|
||||||
val.value.integer = fgetc(fp);
|
val.value.integer = fgetc(fp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("%s cannot be processed with this routine.\n", name);
|
vpi_printf("%s cannot be processed with this routine.\n", name);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue