Ask user before allowing execution of embedded schematic scripts; fix xschemtest netlist hashes

This commit is contained in:
stefan schippers 2026-07-25 09:25:32 +02:00
parent f53b1b5865
commit 36d710d2eb
7 changed files with 96 additions and 25 deletions

View File

@ -4809,12 +4809,20 @@ int callback(const char *win_path, int event, int mx, int my, KeySym key, int bu
break; break;
case ConfigureNotify: case ConfigureNotify:
if(xctx->semaphore >= 2 && !redraw_only) {
xctx->semaphore--;
return 0;
}
dbg(1,"callback(): ConfigureNotify event: %s %dx%d\n", win_path, button, aux); dbg(1,"callback(): ConfigureNotify event: %s %dx%d\n", win_path, button, aux);
resetwin(1, 1, 0, 0, 0); resetwin(1, 1, 0, 0, 0);
draw(); draw();
break; break;
case MotionNotify: case MotionNotify:
if(xctx->semaphore >= 2 && !redraw_only) {
xctx->semaphore--;
return 0;
}
handle_motion_notify(event, key, state, rstate, button, mx, my, handle_motion_notify(event, key, state, rstate, button, mx, my,
aux, draw_xhair, enable_stretch, tabbed_interface, win_path, aux, draw_xhair, enable_stretch, tabbed_interface, win_path,
snap_cursor, wire_draw_active); snap_cursor, wire_draw_active);

View File

@ -60,19 +60,21 @@ const char *tcl_hook2(const char *cmd)
{ {
static char *result = NULL; static char *result = NULL;
static const char *empty=""; static const char *empty="";
char *unescaped_res;
if(cmd == NULL) { if(cmd == NULL) {
my_free(_ALLOC_ID_, &result); my_free(_ALLOC_ID_, &result);
return empty; return empty;
} }
if(strstr(cmd, "tcleval(") == cmd) { if(strstr(cmd, "tcleval(") == cmd) {
unescaped_res = str_replace(cmd, "\\}", "}", 0, -1); char *unescaped_res = NULL;
my_strdup2(_ALLOC_ID_, &unescaped_res, str_replace(cmd, "\\}", "}", 0, -1));
tclvareval("tclpropeval2 {", unescaped_res, "}" , NULL); tclvareval("tclpropeval2 {", unescaped_res, "}" , NULL);
my_free(_ALLOC_ID_, &unescaped_res);
dbg(1, "tcl_hook2: tclresult()=%s\n", tclresult());
my_strdup2(_ALLOC_ID_, &result, tclresult()); my_strdup2(_ALLOC_ID_, &result, tclresult());
/* dbg(0, "tcl_hook2: return: %s\n", result);*/ dbg(1, "tcl_hook2: return 1: %s\n", result);
} else { } else {
/* dbg(0, "tcl_hook2: return: %s\n", cmd); */ dbg(1, "tcl_hook2: return 2: %s\n", cmd);
my_strdup2(_ALLOC_ID_, &result, cmd); my_strdup2(_ALLOC_ID_, &result, cmd);
} }
return result; return result;
@ -4312,10 +4314,15 @@ static char *get_pin_attr(const char *token, int inst, int engineering)
* caveats: only one @spice_get_node is allowed in a string for now. * caveats: only one @spice_get_node is allowed in a string for now.
*/ */
const char *spice_get_node(const char *token) char *spice_get_node(const char *token)
{ {
const char *pos; const char *pos;
static char *s = NULL;
if(token == NULL) {
my_free(_ALLOC_ID_, &s);
return NULL;
}
if((pos = strstr(token, "@spice_get_node "))) { if((pos = strstr(token, "@spice_get_node "))) {
char *node = NULL; char *node = NULL;
char *token2 = NULL; char *token2 = NULL;
@ -4325,7 +4332,6 @@ const char *spice_get_node(const char *token)
size_t len; size_t len;
double val = 0.0; double val = 0.0;
const char *valstr; const char *valstr;
const char *s;
dbg(1, "token=%s\n", token); dbg(1, "token=%s\n", token);
node = my_malloc(_ALLOC_ID_, strlen(token) + 1); node = my_malloc(_ALLOC_ID_, strlen(token) + 1);
@ -4352,13 +4358,14 @@ const char *spice_get_node(const char *token)
node[len] = ' '; node[len] = ' ';
node[len + 1] = '\0'; node[len + 1] = '\0';
} }
s = str_replace(token2, node, valstr, 0, 1); my_strdup2(_ALLOC_ID_, &s, str_replace(token2, node, valstr, 0, 1));
dbg(1, "s=%s\n", s); dbg(1, "s=%s\n", s);
my_free(_ALLOC_ID_, &token2); my_free(_ALLOC_ID_, &token2);
my_free(_ALLOC_ID_, &node); my_free(_ALLOC_ID_, &node);
return s; return s;
} else { } else {
return token; my_strdup2(_ALLOC_ID_, &s, token);
return s;
} }
} }
@ -4526,8 +4533,7 @@ const char *translate(int inst, const char* s)
/* sim_is_xyce = tcleval("sim_is_xyce")[0] == '1' ? 1 : 0; */ /* sim_is_xyce = tcleval("sim_is_xyce")[0] == '1' ? 1 : 0; */
level = xctx->currsch; level = xctx->currsch;
lcc = xctx->hier_attr; lcc = xctx->hier_attr;
size=CADCHUNKALLOC; STR_ALLOC(&result, result_pos, &size);
my_realloc(_ALLOC_ID_, &result,size);
result[0]='\0'; result[0]='\0';
dbg(1, "translate(): substituting props in <%s>, instance <%s>\n", s ? s : "<NULL>" , instname); dbg(1, "translate(): substituting props in <%s>, instance <%s>\n", s ? s : "<NULL>" , instname);
@ -4549,7 +4555,6 @@ const char *translate(int inst, const char* s)
) )
) state=TOK_SEP; ) state=TOK_SEP;
STR_ALLOC(&result, result_pos, &size);
STR_ALLOC(&token, token_pos, &sizetok); STR_ALLOC(&token, token_pos, &sizetok);
if(state==TOK_TOKEN) token[token_pos++]=(char)c; if(state==TOK_TOKEN) token[token_pos++]=(char)c;
else if(state==TOK_SEP) else if(state==TOK_SEP)
@ -4612,9 +4617,10 @@ const char *translate(int inst, const char* s)
if (!strcmp( get_tok_value(prop,"name",0), token+2)) { if (!strcmp( get_tok_value(prop,"name",0), token+2)) {
if(strboolcmp(get_tok_value(prop,"spice_ignore",0), "true")) { if(strboolcmp(get_tok_value(prop,"spice_ignore",0), "true")) {
const char *str_ptr = net_name(inst,i, &multip, 0, 0); const char *str_ptr = net_name(inst,i, &multip, 0, 0);
tmp = strlen(str_ptr) +100 ; tmp = strlen(str_ptr);
STR_ALLOC(&result, tmp + result_pos, &size); STR_ALLOC(&result, tmp + result_pos, &size);
result_pos += my_snprintf(result + result_pos, tmp, "%s", str_ptr); memcpy(result+result_pos,str_ptr, tmp+1);
result_pos+=tmp;
} }
break; break;
} }
@ -4725,13 +4731,14 @@ const char *translate(int inst, const char* s)
len = 3; len = 3;
} else if(idx < 0) { } else if(idx < 0) {
valstr = "-"; valstr = "-";
xctx->tok_size = 5; xctx->tok_size = 1;
len = 5; len = 1;
} else { } else {
valstr = engineering ? dtoa_eng(val, xctx->ev_precision) : dtoa(val); valstr = engineering ? dtoa_eng(val, xctx->ev_precision) : dtoa(val);
len = xctx->tok_size; len = xctx->tok_size;
} }
if(len) { if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size); STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1); memcpy(result+result_pos, valstr, len+1);
result_pos += len; result_pos += len;
@ -4833,6 +4840,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size; len = xctx->tok_size;
} }
if(len) { if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size); STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1); memcpy(result+result_pos, valstr, len+1);
result_pos += len; result_pos += len;
@ -4934,6 +4942,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size; len = xctx->tok_size;
} }
if(len) { if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size); STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1); memcpy(result+result_pos, valstr, len+1);
result_pos += len; result_pos += len;
@ -5000,6 +5009,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size; len = xctx->tok_size;
} }
if(len) { if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size); STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1); memcpy(result+result_pos, valstr, len+1);
result_pos += len; result_pos += len;
@ -5133,6 +5143,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size; len = xctx->tok_size;
} }
if(len) { if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size); STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1); memcpy(result+result_pos, valstr, len+1);
result_pos += len; result_pos += len;
@ -5273,7 +5284,9 @@ const char *translate(int inst, const char* s)
else result[result_pos++]=(char)c; else result[result_pos++]=(char)c;
state=TOK_BEGIN; state=TOK_BEGIN;
} /* else if(state==TOK_SEP) */ } /* else if(state==TOK_SEP) */
else if(state==TOK_BEGIN) result[result_pos++]=(char)c; else if(state==TOK_BEGIN) {
result[result_pos++]=(char)c;
}
if(c=='\0') if(c=='\0')
{ {
result[result_pos]='\0'; result[result_pos]='\0';
@ -5285,7 +5298,10 @@ const char *translate(int inst, const char* s)
/* resolve spice_get_node patterns. /* resolve spice_get_node patterns.
* if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions * if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions
* can be calculated */ * can be calculated */
my_strdup2(_ALLOC_ID_, &result, spice_get_node(tcl_hook2(result)));
my_strdup2(_ALLOC_ID_, &result, tcl_hook2(result));
my_strdup2(_ALLOC_ID_, &result, spice_get_node(result));
if(is_expr(result) && inst >= 0) { if(is_expr(result) && inst >= 0) {
dbg(1, "translate(): expr():%s\n", result); dbg(1, "translate(): expr():%s\n", result);

View File

@ -981,6 +981,7 @@ static void xwin_exit(void)
find_nth(NULL, "", "", 0, 0); /* clear static data in function */ find_nth(NULL, "", "", 0, 0); /* clear static data in function */
trim_chars(NULL, ""); /* clear static data in function */ trim_chars(NULL, ""); /* clear static data in function */
tcl_hook2(NULL); /* clear static data in function */ tcl_hook2(NULL); /* clear static data in function */
spice_get_node(NULL); /* clear static data in function */
save_ascii_string(NULL, NULL, 0); /* clear static data in function */ save_ascii_string(NULL, NULL, 0); /* clear static data in function */
eval_expr_clear_table(); /* clear expression parser data */ eval_expr_clear_table(); /* clear expression parser data */
dbg(1, "xwin_exit(): removing font\n"); dbg(1, "xwin_exit(): removing font\n");

View File

@ -1655,7 +1655,7 @@ extern Ptr_hashentry *ptr_hash_lookup(Ptr_hashtable *hashtable,
extern char *trim_chars(const char *str, const char *sep); extern char *trim_chars(const char *str, const char *sep);
extern char *find_nth(const char *str, const char *sep, const char *quote, int keep_quote, int n); extern char *find_nth(const char *str, const char *sep, const char *quote, int keep_quote, int n);
extern int isonlydigit(const char *s); extern int isonlydigit(const char *s);
extern const char *spice_get_node(const char *token); extern char *spice_get_node(const char *token);
extern char *get_fqdevice(const char *param, int modelparam, const char *instname); extern char *get_fqdevice(const char *param, int modelparam, const char *instname);
extern const char *translate(int inst, const char* s); extern const char *translate(int inst, const char* s);
extern const char* translate2(Lcc *lcc, int level, char* s); extern const char* translate2(Lcc *lcc, int level, char* s);

View File

@ -6924,8 +6924,7 @@ proc tclpropeval {s instname symname} {
# this hook is called in translate() if whole string is contained in a tcleval(...) construct # this hook is called in translate() if whole string is contained in a tcleval(...) construct
proc tclpropeval2 {s} { proc tclpropeval2 {s} {
global debug_tcleval env path debug_var sch_basename global debug_tcleval env path debug_var sch_basename xschem_execute_scripts has_x
set raw_level [xschem get raw_level] set raw_level [xschem get raw_level]
set netlist_type [xschem get netlist_type] set netlist_type [xschem get netlist_type]
# puts "tclpropeval2: s=|$s|" # puts "tclpropeval2: s=|$s|"
@ -6956,9 +6955,43 @@ proc tclpropeval2 {s} {
regsub {\)([ \n\t]*)$} $s {\1} s regsub {\)([ \n\t]*)$} $s {\1} s
# puts "tclpropeval2: s=|$s|" # puts "tclpropeval2: s=|$s|"
# puts "tclpropeval2: subst $s=|[subst $s]|" # puts "tclpropeval2: subst $s=|[subst $s]|"
if { [catch {uplevel #0 "subst \{$s\}"} res] } { if { $xschem_execute_scripts eq {no} } {
if { $debug_tcleval > 0} { puts "tclpropeval2 warning: $s --> $res"}
set res ?\n set res ?\n
return $res
} elseif { $xschem_execute_scripts eq {ask}} {
if {[info exists has_x]} {
xschem set semaphore [expr {[xschem get semaphore] +1}]
set msg " Allow xschem to execute scripts embedded in schematics?\n\n"
append msg " WARNING:\n"
append msg " Allowing script execution is a potential security vulnerability,\n"
append msg " Do it only for schematics obtained from trusted sources.\n\n"
append msg " To avoid this message look for variable 'xschem_execute_scripts'\n"
append msg " in your xschemrc file,\n"
append msg " set it to 'yes' to permanently ENABLE scripts,\n"
append msg " or set it to 'no' to permanently DISABLE scripts.\n"
append msg " Current (default) setting is 'ask'."
set answer [alert_ $msg {} 0 1]
xschem set semaphore [expr {[xschem get semaphore] -1}]
# set answer [tk_messageBox -parent [xschem get topwindow] -message $msg -type yesno]
if {$answer eq {1}} {
set xschem_execute_scripts yes
} elseif {$answer eq {0}} {
set xschem_execute_scripts no
}
} else {
set xschem_execute_scripts yes
}
}
if { $xschem_execute_scripts eq {yes} } {
focus [xschem get top_path].drw
if { [catch {uplevel #0 "subst \{$s\}"} res] } {
if { $debug_tcleval > 0} { puts "tclpropeval2 warning: $s --> $res"}
set res ?\n
}
} else {
set res ?\n
return $res
} }
# puts "tclpropeval2: res=|$res|" # puts "tclpropeval2: res=|$res|"
return $res return $res
@ -9731,7 +9764,8 @@ set tctx::global_list {
top_is_subckt transparent_svg undo_type unselect_partial_sel_wires uppercase_subckt top_is_subckt transparent_svg undo_type unselect_partial_sel_wires uppercase_subckt
use_cursor_for_selection use_lab_wire use_label_prefix use_tclreadline user_wants_copy_cell use_cursor_for_selection use_lab_wire use_label_prefix use_tclreadline user_wants_copy_cell
verilog_2001 verilog_bitblast verilog_2001 verilog_bitblast
viewdata_fileid viewdata_filename viewdata_w xschem_libs xschem_listen_port zoom_full_center viewdata_fileid viewdata_filename viewdata_w xschem_execute_scripts xschem_libs
xschem_listen_port zoom_full_center
} }
## list of global arrays to save/restore on context switching ## list of global arrays to save/restore on context switching
@ -11551,6 +11585,7 @@ set_ne terminal xterm
# xschem tcp port number (listen to port and execute commands from there if set) # xschem tcp port number (listen to port and execute commands from there if set)
# set a port number in xschemrc if you want accept remote connections. # set a port number in xschemrc if you want accept remote connections.
set_ne xschem_listen_port {} set_ne xschem_listen_port {}
set_ne xschem_execute_scripts ask
# server for bespice waveform connection (listen to port and send commands to bespice if set) # server for bespice waveform connection (listen to port and send commands to bespice if set)
# set a port number in xschemrc if you want xschem to be able to cross-probe to bespice # set a port number in xschemrc if you want xschem to be able to cross-probe to bespice

View File

@ -535,6 +535,17 @@
#### set xschem listening port; default: not enabled #### set xschem listening port; default: not enabled
# set xschem_listen_port 2021 # set xschem_listen_port 2021
###########################################################################
#### EXECUTE SCRIPTS WITH 'tcleval(...)' or '@tcleval(...)'
###########################################################################
#### possible values:
#### yes: allow scripts.
#### no: do not allow scripts, always return empty result.
#### ask: (default) ask to the user if GUI is present. If no GUI is present
#### then allow scripts.
#### Default: ask
# set xschem_execute_scripts yes
########################################################################### ###########################################################################
#### BESPICE WAVE SOCKET CONNECTION #### BESPICE WAVE SOCKET CONNECTION
########################################################################### ###########################################################################

View File

@ -190,12 +190,12 @@ proc test_xschem_simulation {{f simulate_ff.sch}} {
proc netlist_test {} { proc netlist_test {} {
global netlist_dir global netlist_dir
foreach {f t h} { foreach {f t h} {
rom8k.sch spice 834970168 rom8k.sch spice 33778382
greycnt.sch verilog 1945914565 greycnt.sch verilog 1945914565
autozero_comp.sch spice 4088769413 autozero_comp.sch spice 4088769413
test_generators.sch spice 2372200619 test_generators.sch spice 2372200619
inst_sch_select.sch spice 1842909154 inst_sch_select.sch spice 1842909154
test_bus_tap.sch spice 3363212799 test_bus_tap.sch spice 1953773013
loading.sch vhdl 2975204502 loading.sch vhdl 2975204502
mos_power_ampli.sch spice 2505489310 mos_power_ampli.sch spice 2505489310
hierarchical_tedax.sch tedax 998070173 hierarchical_tedax.sch tedax 998070173