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;
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);
resetwin(1, 1, 0, 0, 0);
draw();
break;
case MotionNotify:
if(xctx->semaphore >= 2 && !redraw_only) {
xctx->semaphore--;
return 0;
}
handle_motion_notify(event, key, state, rstate, button, mx, my,
aux, draw_xhair, enable_stretch, tabbed_interface, win_path,
snap_cursor, wire_draw_active);

View File

@ -60,19 +60,21 @@ const char *tcl_hook2(const char *cmd)
{
static char *result = NULL;
static const char *empty="";
char *unescaped_res;
if(cmd == NULL) {
my_free(_ALLOC_ID_, &result);
return empty;
}
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);
my_free(_ALLOC_ID_, &unescaped_res);
dbg(1, "tcl_hook2: tclresult()=%s\n", 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 {
/* dbg(0, "tcl_hook2: return: %s\n", cmd); */
dbg(1, "tcl_hook2: return 2: %s\n", cmd);
my_strdup2(_ALLOC_ID_, &result, cmd);
}
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.
*/
const char *spice_get_node(const char *token)
char *spice_get_node(const char *token)
{
const char *pos;
static char *s = NULL;
if(token == NULL) {
my_free(_ALLOC_ID_, &s);
return NULL;
}
if((pos = strstr(token, "@spice_get_node "))) {
char *node = NULL;
char *token2 = NULL;
@ -4325,7 +4332,6 @@ const char *spice_get_node(const char *token)
size_t len;
double val = 0.0;
const char *valstr;
const char *s;
dbg(1, "token=%s\n", token);
node = my_malloc(_ALLOC_ID_, strlen(token) + 1);
@ -4352,13 +4358,14 @@ const char *spice_get_node(const char *token)
node[len] = ' ';
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);
my_free(_ALLOC_ID_, &token2);
my_free(_ALLOC_ID_, &node);
return s;
} 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; */
level = xctx->currsch;
lcc = xctx->hier_attr;
size=CADCHUNKALLOC;
my_realloc(_ALLOC_ID_, &result,size);
STR_ALLOC(&result, result_pos, &size);
result[0]='\0';
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;
STR_ALLOC(&result, result_pos, &size);
STR_ALLOC(&token, token_pos, &sizetok);
if(state==TOK_TOKEN) token[token_pos++]=(char)c;
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(strboolcmp(get_tok_value(prop,"spice_ignore",0), "true")) {
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);
result_pos += my_snprintf(result + result_pos, tmp, "%s", str_ptr);
memcpy(result+result_pos,str_ptr, tmp+1);
result_pos+=tmp;
}
break;
}
@ -4725,13 +4731,14 @@ const char *translate(int inst, const char* s)
len = 3;
} else if(idx < 0) {
valstr = "-";
xctx->tok_size = 5;
len = 5;
xctx->tok_size = 1;
len = 1;
} else {
valstr = engineering ? dtoa_eng(val, xctx->ev_precision) : dtoa(val);
len = xctx->tok_size;
}
if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
@ -4833,6 +4840,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size;
}
if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
@ -4934,6 +4942,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size;
}
if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
@ -5000,6 +5009,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size;
}
if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
@ -5133,6 +5143,7 @@ const char *translate(int inst, const char* s)
len = xctx->tok_size;
}
if(len) {
len = strlen(valstr);
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
@ -5273,7 +5284,9 @@ const char *translate(int inst, const char* s)
else result[result_pos++]=(char)c;
state=TOK_BEGIN;
} /* 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')
{
result[result_pos]='\0';
@ -5285,7 +5298,10 @@ const char *translate(int inst, const char* s)
/* resolve spice_get_node patterns.
* if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions
* 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) {
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 */
trim_chars(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 */
eval_expr_clear_table(); /* clear expression parser data */
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 *find_nth(const char *str, const char *sep, const char *quote, int keep_quote, int n);
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 const char *translate(int inst, const 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
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 netlist_type [xschem get netlist_type]
# puts "tclpropeval2: s=|$s|"
@ -6956,9 +6955,43 @@ proc tclpropeval2 {s} {
regsub {\)([ \n\t]*)$} $s {\1} s
# puts "tclpropeval2: s=|$s|"
# puts "tclpropeval2: subst $s=|[subst $s]|"
if { [catch {uplevel #0 "subst \{$s\}"} res] } {
if { $debug_tcleval > 0} { puts "tclpropeval2 warning: $s --> $res"}
if { $xschem_execute_scripts eq {no} } {
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|"
return $res
@ -9731,7 +9764,8 @@ set tctx::global_list {
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
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
@ -11551,6 +11585,7 @@ set_ne terminal xterm
# 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_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)
# 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_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
###########################################################################

View File

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