fixed path created by ngdirname in Windows. Also added const to parameters whose arguments do not change and fixed some potential buffer overruns.

This commit is contained in:
Jim Monte 2020-01-31 00:39:27 -05:00 committed by Holger Vogt
parent 33bb874678
commit 2035442a9f
7 changed files with 172 additions and 111 deletions

View File

@ -13,7 +13,7 @@ Modified 1999 Emmanuel Rouat
#include "ngspice/hlpdefs.h"
#include "ngspice/suffix.h"
extern char *cp_tildexpand(char *string);
extern char *cp_tildexpand(const char *string);
char *hlp_directory;
extern char *hlp_filelist[];

View File

@ -20,6 +20,7 @@ Author: 1985 Wayne A. Christopher
#include "ngspice/compatmode.h"
#include "ngspice/cpdefs.h"
#include "ngspice/dstring.h"
#include "ngspice/dvec.h"
#include "ngspice/ftedefs.h"
#include "ngspice/fteext.h"
@ -119,7 +120,8 @@ static void inp_stripcomments_line(char *s, bool cs);
static void inp_fix_for_numparam(
struct names *subckt_w_params, struct card *deck);
static void inp_remove_excess_ws(struct card *deck);
static void expand_section_references(struct card *deck, char *dir_name);
static void expand_section_references(struct card *deck,
const char *dir_name);
static void inp_grab_func(struct function_env *, struct card *deck);
static void inp_fix_inst_calls_for_numparam(
struct names *subckt_w_params, struct card *deck);
@ -163,7 +165,7 @@ static void inp_check_syntax(struct card *deck);
static char *inp_spawn_brace(char *s);
static char *inp_pathresolve(const char *name);
static char *inp_pathresolve_at(char *name, char *dir);
static char *inp_pathresolve_at(const char *name, const char *dir);
static char *search_plain_identifier(char *str, const char *identifier);
static struct nscope *inp_add_levels(struct card *deck);
@ -184,8 +186,8 @@ struct inp_read_t {
int line_number;
};
static struct inp_read_t inp_read(
FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile);
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
bool comfile, bool intfile);
#ifndef XSPICE
@ -302,8 +304,7 @@ static struct card *find_section_definition(struct card *c, char *name)
return NULL;
}
static struct library *read_a_lib(char *y, char *dir_name)
static struct library *read_a_lib(const char *y, const char *dir_name)
{
char *yy, *y_resolved;
@ -355,7 +356,8 @@ static struct library *read_a_lib(char *y, char *dir_name)
txfree(y_resolved);
return lib;
}
} /* end of function read_a_lib */
static struct names *new_names(void)
@ -587,8 +589,8 @@ static COMPATMODE_T ngspice_compat_mode(void)
remove the 'level' entries from each card
*-------------------------------------------------------------------------*/
struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile,
bool *expr_w_temper_p)
struct card *inp_readall(FILE *fp, const char *dir_name,
bool comfile, bool intfile, bool *expr_w_temper_p)
{
struct card *cc;
struct inp_read_t rv;
@ -764,8 +766,8 @@ struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile,
}
struct inp_read_t inp_read(
FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile)
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
bool comfile, bool intfile)
/* fp: in, pointer to file to be read,
call_depth: in, nested call to fcn
dir_name: in, name of directory of file to be read
@ -1266,18 +1268,19 @@ is_plain_filename(const char *p)
#endif
FILE *inp_pathopen(char *name, char *mode)
FILE *inp_pathopen(const char *name, const char *mode)
{
char *path = inp_pathresolve(name);
char * const path = inp_pathresolve(name);
if (path) {
FILE *fp = fopen(path, mode);
tfree(path);
txfree(path);
return fp;
}
return NULL;
}
return (FILE *) NULL;
} /* end of function inp_pathopen */
/*-------------------------------------------------------------------------*
@ -1287,7 +1290,6 @@ FILE *inp_pathopen(char *name, char *mode)
static char *inp_pathresolve(const char *name)
{
char buf[BSIZE_SP];
struct variable *v;
struct stat st;
@ -1297,10 +1299,17 @@ static char *inp_pathresolve(const char *name)
if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) &&
name[0] == DIR_TERM_LINUX && isalpha_c(name[1]) &&
name[2] == DIR_TERM_LINUX) {
strcpy(buf, name);
DS_CREATE(ds, 100);
if (ds_cat_str(&ds, name) != 0) {
fprintf(stderr, "Unable to copy string while resolving path");
controlled_exit(EXIT_FAILURE);
}
char *const buf = ds_get_buf(&ds);
buf[0] = buf[1];
buf[1] = ':';
return inp_pathresolve(buf);
char * const resolved_path = inp_pathresolve(buf);
ds_free(&ds);
return resolved_path;
}
#endif
@ -1312,55 +1321,77 @@ static char *inp_pathresolve(const char *name)
/* fail if this was an absolute filename or if there is no sourcepath var
*/
if (is_absolute_pathname(name) ||
!cp_getvar("sourcepath", CP_LIST, &v, 0))
return NULL;
for (; v; v = v->va_next) {
switch (v->va_type) {
case CP_STRING:
cp_wstrip(v->va_string);
(void) sprintf(buf, "%s%s%s",
v->va_string, DIR_PATHSEP, name);
break;
case CP_NUM:
(void) sprintf(buf, "%d%s%s", v->va_num, DIR_PATHSEP, name);
break;
case CP_REAL: /* This is foolish */
(void) sprintf(buf, "%g%s%s", v->va_real, DIR_PATHSEP, name);
break;
default:
fprintf(stderr,
"ERROR: enumeration value `CP_BOOL' or `CP_LIST' not "
"handled in inp_pathresolve\nAborting...\n");
controlled_exit(EXIT_FAILURE);
break;
}
if (stat(buf, &st) == 0)
return copy(buf);
!cp_getvar("sourcepath", CP_LIST, &v, 0)) {
return (char *) NULL;
}
return (NULL);
}
{
DS_CREATE(ds, 100);
for (; v; v = v->va_next) {
int rc_ds;
ds_clear(&ds); /* empty buffer */
switch (v->va_type) {
case CP_STRING:
cp_wstrip(v->va_string);
rc_ds = ds_cat_printf(&ds, "%s%s%s",
v->va_string, DIR_PATHSEP, name);
break;
case CP_NUM:
rc_ds = ds_cat_printf(&ds, "%d%s%s",
v->va_num, DIR_PATHSEP, name);
break;
case CP_REAL: /* This is foolish */
rc_ds = ds_cat_printf(&ds, "%g%s%s",
v->va_real, DIR_PATHSEP, name);
break;
default:
fprintf(stderr,
"ERROR: enumeration value `CP_BOOL' or `CP_LIST' "
"not handled in inp_pathresolve\nAborting...\n");
controlled_exit(EXIT_FAILURE);
}
if (rc_ds != 0) { /* unable to build string */
(void) fprintf(cp_err,
"Unable to build path name in inp_pathresolve");
controlled_exit(EXIT_FAILURE);
}
/* Test if the file is found */
{
const char * const buf = ds_get_buf(&ds);
if (stat(buf, &st) == 0) {
char * const buf_cpy = dup_string(
buf, ds_get_length(&ds));
ds_free(&ds);
return buf_cpy;
}
/* Else contiue with next attempt */
}
} /* end of loop over linked variables */
ds_free(&ds);
} /* end of block trying to find a valid name */
return (char *) NULL;
} /* end of function inp_pathresolve */
static char *inp_pathresolve_at(char *name, char *dir)
static char *inp_pathresolve_at(const char *name, const char *dir)
{
char buf[BSIZE_SP], *end;
/* if name is an absolute path name,
* or if we haven't anything to prepend anyway
*/
if (is_absolute_pathname(name) || !dir || !dir[0])
if (is_absolute_pathname(name) || !dir || !dir[0]) {
return inp_pathresolve(name);
}
if (name[0] == '~' && name[1] == '/') {
char *y = cp_tildexpand(name);
char * const y = cp_tildexpand(name);
if (y) {
char *r = inp_pathresolve(y);
tfree(y);
char * const r = inp_pathresolve(y);
txfree(y);
return r;
}
}
@ -1371,28 +1402,49 @@ static char *inp_pathresolve_at(char *name, char *dir)
* sourcepath
*/
strcpy(buf, ".");
{
DS_CREATE(ds, 100);
if (ds_cat_printf(&ds, ".%c%s", DIR_TERM, name) != 0) {
(void) fprintf(cp_err,
"Unable to build \".\" path name in inp_pathresolve_at");
controlled_exit(EXIT_FAILURE);
}
char * const r = inp_pathresolve(ds_get_buf(&ds));
ds_free(&ds);
if (r != (char *) NULL) {
return r;
}
}
end = strchr(buf, '\0');
if (end[-1] != DIR_TERM)
*end++ = DIR_TERM;
{
DS_CREATE(ds, 100);
int rc_ds = 0;
rc_ds |= ds_cat_str(&ds, dir); /* copy the dir name */
const size_t n = ds_get_length(&ds); /* end of copied dir name */
strcpy(end, name);
/* Append a directory separator if not present already */
const char ch_last = n > 0 ? dir[n - 1] : '\0';
if (ch_last != DIR_TERM
#ifdef _WIN32
&& ch_last != DIR_TERM_LINUX
#endif
) {
rc_ds |= ds_cat_char(&ds, DIR_TERM);
}
rc_ds |= ds_cat_str(&ds, name); /* append the file name */
char *r = inp_pathresolve(buf);
if (r)
if (rc_ds != 0) {
(void) fprintf(cp_err, "Unable to build \"dir\" path name "
"in inp_pathresolve_at");
controlled_exit(EXIT_FAILURE);
}
char * const r = inp_pathresolve(ds_get_buf(&ds));
ds_free(&ds);
return r;
}
} /* end of function inp_pathresolve_at */
strcpy(buf, dir);
end = strchr(buf, '\0');
if (end[-1] != DIR_TERM)
*end++ = DIR_TERM;
strcpy(end, name);
return inp_pathresolve(buf);
}
/*-------------------------------------------------------------------------*
@ -2746,7 +2798,7 @@ static void inp_remove_excess_ws(struct card *c)
}
static struct card *expand_section_ref(struct card *c, char *dir_name)
static struct card *expand_section_ref(struct card *c, const char *dir_name)
{
char *line = c->line;
@ -2847,7 +2899,7 @@ static struct card *expand_section_ref(struct card *c, char *dir_name)
* just those references occuring in the given library section definition
*/
static void expand_section_references(struct card *c, char *dir_name)
static void expand_section_references(struct card *c, const char *dir_name)
{
for (; c; c = c->nextcard)
if (ciprefix(".lib", c->line))

View File

@ -390,7 +390,7 @@ static wordlist_l *brac2(const char *string,
/* Expand tildes. */
char *cp_tildexpand(char *string)
char *cp_tildexpand(const char *string)
{
/* Attempt to do the tilde expansion */
char * const result = tildexpand(string);

View File

@ -79,8 +79,8 @@ extern void cp_pushcontrol(void);
/* glob.c */
extern bool cp_globmatch(char *p, char *s);
extern char *cp_tildexpand(char *string);
extern bool cp_globmatch(const char *p, const char *s);
extern char *cp_tildexpand(const char *string);
extern char cp_cbrac;
extern char cp_ccurl;
extern char cp_comma;

View File

@ -214,8 +214,9 @@ extern void inp_source(const char *file);
int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile);
extern void inp_casefix(char *string);
extern void inp_list(FILE *file, struct card *deck, struct card *extras, int type);
extern struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_temper);
extern FILE *inp_pathopen(char *name, char *mode);
struct card *inp_readall(FILE *fp, const char *dir_name,
bool comfile, bool intfile, bool *expr_w_temper_p);
extern FILE *inp_pathopen(const char *name, const char *mode);
extern char *search_identifier(char *str, const char *identifier, char *str_begin);
extern char *find_assignment(const char *s);
extern char *find_back_assignment(const char *s, const char *start);

View File

@ -140,7 +140,7 @@
#ifdef HAS_WINGUI
#include "ngspice/wstdio.h"
#define HAS_PROGREP
extern void SetAnalyse(char *Analyse, int Percent);
extern void SetAnalyse(const char *Analyse, int Percent);
#endif
#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
@ -299,7 +299,7 @@ extern int sh_vfprintf(FILE *fd, const char *format, va_list args);
extern int sh_fputs(const char *input, FILE *fd);
extern int sh_fputc(int input, FILE *fd);
extern int sh_putc(int input, FILE *fd);
extern void SetAnalyse(char *analyse, int percent);
extern void SetAnalyse(const char *analyse, int percent);
#define HAS_PROGREP

View File

@ -189,43 +189,51 @@ basename(const char *name)
#if defined(HAS_WINGUI) || defined(_MSC_VER) || defined(__MINGW32__)
char *
ngdirname(const char *name)
/* This function returns the path portion of name or "." if it is NULL.
* The returned string is a new allocation that must be freed by the
* caller */
char *ngdirname(const char *name)
{
char *ret;
const char *end = NULL;
int start = 0;
if(name && ((name[0] >= 'a' && name[0] <= 'z') ||
(name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':')
start = 2;
if(name) {
const char *p = name + start;
for(; *p; p++)
if(*p == '/' || *p == '\\')
end = p;
/* If name not given, return "." */
if (name == (char *) NULL) {
return dup_string(".", 1);
}
if(end && end == name + start)
end++;
/* Offset to start of path name after any drive letter present */
const int start = (((name[0] >= 'a' && name[0] <= 'z') ||
(name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':') ? 2 : 0;
if(end)
ret = copy_substring(name, end);
else {
char *p = TMALLOC(char, 4);
ret = p;
if(start) {
/* Find last dir separator, if any, and return the input directory up to
* that separator or including it if it is the 1st char after any drive
*specification. */
{
const char *p0 = name + start; /* 1st char past drive */
const char *p;
for (p = p0 + strlen(name + start) - 1; p >= p0; --p) {
const char *ch_cur = *p;
if (ch_cur == '/' || ch_cur == '\\') { /* at last dir sep */
/* Stop copy at last dir sep or right after if
* it is the first char after any drive spec.
* In the second case return "[drive]<dir sep>" */
const char * const end = p + (p == p0);
return copy_substring(name, end);
}
}
}
/* No directory separator found so return "[drive]." */
{
char * const ret = TMALLOC(char, 2 + start);
char *p = ret;
if (start) { /* Add drive letter if found */
*p++ = name[0];
*p++ = name[1];
}
*p++ = '.';
*p++ = '\0';
*p = '\0';
return ret;
}
return ret;
}
} /* end of function ngdirname */
#else