Properly terminate a snprintf() call.

snprintf() copies at most N characters, but the string may not be
terminated correctly. This patch uses sizeof() so that the snprintf()
call matches the size of the buffer and adds code to insert a NULL as
the last character of the string.
This commit is contained in:
Cary R 2011-05-02 09:09:22 -07:00 committed by Stephen Williams
parent c2225f679b
commit e85c43c232
9 changed files with 59 additions and 38 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2008-2010 Cary R. (cygcary@yahoo.com) * Copyright (C) 2008-2011 Cary R. (cygcary@yahoo.com)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -87,12 +87,13 @@ static PLI_INT32 sys_clog2_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
/* We can have a maximum of one argument. */ /* We can have a maximum of one argument. */
if (vpi_scan(argv) != 0) { if (vpi_scan(argv) != 0) {
char msg [64]; char msg[64];
unsigned argc; unsigned argc;
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
argc = 1; argc = 1;
while (vpi_scan(argv)) argc += 1; while (vpi_scan(argv)) argc += 1;

View File

@ -414,10 +414,11 @@ static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* $dumpfile must be called before $dumpvars starts! */ /* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) { if (dumpvars_status != 0) {
char msg [64]; char msg[64];
snprintf(msg, 64, "FST warning: %s:%d:", snprintf(msg, sizeof(msg), "FST warning: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s called after $dumpvars started,\n", msg, name); vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n", vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path); (int) strlen(msg), " ", dump_path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2011 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -469,10 +469,11 @@ static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* $dumpfile must be called before $dumpvars starts! */ /* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) { if (dumpvars_status != 0) {
char msg [64]; char msg[64];
snprintf(msg, 64, "LXT warning: %s:%d:", snprintf(msg, sizeof(msg), "LXT warning: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s called after $dumpvars started,\n", msg, name); vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n", vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path); (int) strlen(msg), " ", dump_path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -525,10 +525,11 @@ static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* $dumpfile must be called before $dumpvars starts! */ /* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) { if (dumpvars_status != 0) {
char msg [64]; char msg[64];
snprintf(msg, 64, "LXT2 warning: %s:%d:", snprintf(msg, sizeof(msg), "LXT2 warning: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s called after $dumpvars started,\n", msg, name); vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n", vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path); (int) strlen(msg), " ", dump_path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2011 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -133,7 +133,7 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
s_vpi_vlog_info info; s_vpi_vlog_info info;
s_vpi_value fmt; s_vpi_value fmt;
s_vpi_value res; s_vpi_value res;
char msg [64]; char msg[64];
char*cp; char*cp;
int idx; int idx;
int flag = 0; int flag = 0;
@ -148,9 +148,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* Check for the start of a format string. */ /* Check for the start of a format string. */
cp = strchr(fmt.value.str, '%'); cp = strchr(fmt.value.str, '%');
if (cp == 0) { if (cp == 0) {
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s is missing a format code.\n", msg, name); vpi_printf("%s %s is missing a format code.\n", msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
@ -187,9 +188,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
case 'S': case 'S':
break; break;
default: default:
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s has an invalid format string:\n", msg, name); vpi_printf("%s %s has an invalid format string:\n", msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
@ -199,9 +201,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* Warn if there is any trailing garbage. */ /* Warn if there is any trailing garbage. */
if (*(cp+1) != '\0') { if (*(cp+1) != '\0') {
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Skipping trailing garbage in %s's format string:\n", vpi_printf("%s Skipping trailing garbage in %s's format string:\n",
msg, name); msg, name);
@ -244,9 +247,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
*sp == '_' || *sp == '_' ||
((tp = strrchr(sp, '-')) && tp != sp)) { ((tp = strrchr(sp, '-')) && tp != sp)) {
res.value.str = "x"; res.value.str = "x";
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Invalid decimal value passed to %s:\n", vpi_printf("%s Invalid decimal value passed to %s:\n",
msg, name); msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
@ -263,9 +267,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
if (sp_len != strspn(sp, "-01234567_xXzZ") || if (sp_len != strspn(sp, "-01234567_xXzZ") ||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) { *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
res.value.str = "x"; res.value.str = "x";
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Invalid octal value passed to %s:\n", vpi_printf("%s Invalid octal value passed to %s:\n",
msg, name); msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
@ -284,9 +289,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
if (sp_len != strspn(sp, "-0123456789aAbBcCdDeEfF_xXzZ") || if (sp_len != strspn(sp, "-0123456789aAbBcCdDeEfF_xXzZ") ||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) { *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
res.value.str = "x"; res.value.str = "x";
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Invalid hex value passed to %s:\n", vpi_printf("%s Invalid hex value passed to %s:\n",
msg, name); msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
@ -303,9 +309,10 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
if (sp_len != strspn(sp, "-01_xXzZ") || if (sp_len != strspn(sp, "-01_xXzZ") ||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) { *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
res.value.str = "x"; res.value.str = "x";
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Invalid binary value passed to %s:\n", vpi_printf("%s Invalid binary value passed to %s:\n",
msg, name); msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp); vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
@ -325,18 +332,20 @@ static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
if (*end) { if (*end) {
/* We had an invalid value passed. */ /* We had an invalid value passed. */
if (end == sp) { if (end == sp) {
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Invalid real value passed to " vpi_printf("%s Invalid real value passed to "
"%s:\n", msg, name); "%s:\n", msg, name);
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ",
sp); sp);
/* We have extra garbage at the end. */ /* We have extra garbage at the end. */
} else { } else {
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s Extra character(s) \"%s\" found " vpi_printf("%s Extra character(s) \"%s\" found "
"in %s's real string:\n", "in %s's real string:\n",
msg, end, name); msg, end, name);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -86,11 +86,12 @@ char *get_filename(vpiHandle callh, const char *name, vpiHandle file)
len = strlen(val.value.str); len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) { for (idx = 0; idx < len; idx++) {
if (! isprint((int)val.value.str[idx])) { if (! isprint((int)val.value.str[idx])) {
char msg [64]; char msg[64];
char *esc_fname = as_escaped(val.value.str); char *esc_fname = as_escaped(val.value.str);
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s's file name argument contains non-" vpi_printf("%s %s's file name argument contains non-"
"printable characters.\n", msg, name); "printable characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_fname); vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_fname);
@ -107,12 +108,13 @@ void check_for_extra_args(vpiHandle argv, vpiHandle callh, const char *name,
{ {
/* Check that there are no extra arguments. */ /* Check that there are no extra arguments. */
if (vpi_scan(argv) != 0) { if (vpi_scan(argv) != 0) {
char msg [64]; char msg[64];
unsigned argc; unsigned argc;
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
argc = 1; argc = 1;
while (vpi_scan(argv)) argc += 1; while (vpi_scan(argv)) argc += 1;
@ -242,12 +244,13 @@ PLI_INT32 sys_no_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
/* Make sure there are no arguments. */ /* Make sure there are no arguments. */
if (argv != 0) { if (argv != 0) {
char msg [64]; char msg[64];
unsigned argc; unsigned argc;
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
argc = 0; argc = 0;
while (vpi_scan(argv)) argc += 1; while (vpi_scan(argv)) argc += 1;

View File

@ -304,7 +304,9 @@ static PLI_INT32 sys_readmem_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
char path[4096]; char path[4096];
for (idx = 0; idx < sl_count; idx += 1) { for (idx = 0; idx < sl_count; idx += 1) {
snprintf(path, 4096, "%s/%s", search_list[idx], fname); snprintf(path, sizeof(path), "%s/%s",
search_list[idx], fname);
path[sizeof(path)-1] = 0;
if ((file = fopen(path, "r"))) break; if ((file = fopen(path, "r"))) break;
} }
} }
@ -449,11 +451,12 @@ static PLI_INT32 sys_readmempath_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
len = strlen(val.value.str); len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) { for (idx = 0; idx < len; idx++) {
if (! isprint((int)val.value.str[idx])) { if (! isprint((int)val.value.str[idx])) {
char msg [64]; char msg[64];
char *esc_path = as_escaped(val.value.str); char *esc_path = as_escaped(val.value.str);
snprintf(msg, 64, "WARNING: %s:%d:", snprintf(msg, sizeof(msg), "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s's argument contains non-printable " vpi_printf("%s %s's argument contains non-printable "
"characters.\n", msg, name); "characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_path); vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -445,10 +445,11 @@ static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* $dumpfile must be called before $dumpvars starts! */ /* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) { if (dumpvars_status != 0) {
char msg [64]; char msg[64];
snprintf(msg, 64, "VCD warning: %s:%d:", snprintf(msg, sizeof(msg), "VCD warning: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
vpi_printf("%s %s called after $dumpvars started,\n", msg, name); vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n", vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path); (int) strlen(msg), " ", dump_path);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2008-2010 Cary R. (cygcary@yahoo.com) * Copyright (C) 2008-2011 Cary R. (cygcary@yahoo.com)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -84,12 +84,13 @@ static PLI_INT32 simparam_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name_ext)
/* We can have a maximum of two arguments. */ /* We can have a maximum of two arguments. */
if (vpi_scan(argv) != 0) { if (vpi_scan(argv) != 0) {
char msg [64]; char msg[64];
unsigned argc; unsigned argc;
snprintf(msg, 64, "ERROR: %s:%d:", snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh), vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
msg[sizeof(msg)-1] = 0;
argc = 1; argc = 1;
while (vpi_scan(argv)) argc += 1; while (vpi_scan(argv)) argc += 1;