Tcl Source Code

View Ticket
Login
Ticket UUID: ba68d1e9484a3a92449fdaab4c377b534842c0e0
Title: Errors that occur when using interp eval do not give relevant line number and filename locations
Type: Bug Version: any
Submitter: anonymous Created on: 2025-02-25 17:00:06
Subsystem: 20. [interp] Assigned To: sebres
Priority: 3 Low Severity: Cosmetic
Status: Closed Last Modified: 2025-03-06 19:24:12
Resolution: Fixed Closed By: sebres
    Closed on: 2025-03-06 19:24:12
Description:
More details can be found here: https://stackoverflow.com/questions/78134384/how-to-get-line-number-and-filename-locations-for-errors-that-occur-while-using

To summarize, though, when an error occurs while using interp eval, the error outputs the location of the interp eval call, rather than the location of the actual erroneous code being evaluated.

This may make sense from the perspective of the caller of interp eval.
However, it creates difficulties in the context of implementing something like a plugin system that interp evals scripts, as the writers of the plugin scripts would receive less useful information than might be desired.

Some example code and their outputs:

Example A:
#!/bin/sh    
# This line continues for Tcl, but is a single line for 'sh' \    
exec tclsh "$0" ${1+"$@"}    
    
::safe::interpCreate i    
i eval {expr {"a" + 1}}

Example A Output:

./example.tcl 
can't use non-numeric string as operand of "+"
    invoked from within
"expr {"a" + 1}"
    invoked from within
"i eval {expr {"a" + 1}}"
    (file "./example.tcl" line 6)

Example B:
#!/bin/sh    
# This line continues for Tcl, but is a single line for 'sh' \    
exec tclsh "$0" ${1+"$@"}    
    
::safe::interpCreate i    
i eval [list expr {"a" + 1}]

Example B output:
./example.tcl 
can't use non-numeric string as operand of "+"
    while executing
"expr {"a" + 1}"
    invoked from within
"i eval [list expr {"a" + 1}]"
    (file "./example.tcl" line 6)

Example C:
#!/bin/sh    
# This line continues for Tcl, but is a single line for 'sh' \    
exec tclsh "$0" ${1+"$@"}    
    
::safe::interpCreate i    
i eval [list expr [list "a" + 1]]

Example C output:
./example.tcl 
invalid bareword "a"
in expression "a + 1";
should be "$a" or "{a}" or "a(...)" or ...
    (parsing expression "a + 1")
    invoked from within
"expr {a + 1}"
    invoked from within
"i eval [list expr [list "a" + 1]]"
    (file "./example.tcl" line 6)
User Comments: sebres added on 2025-03-06 19:24:12:

Fixed now in [5cd276dee1c2a46f], tests pass, thus close.


sebres added on 2025-03-06 19:12:06:

Found it: the issue has been caused by the bug in Tcl_GetReturnOptions, what sets the errorLine from rethrown error from invokehidden in AliasLoad (so it contains the line number from this proc), but without the errorInfo (which initially empty, but hereafter got filled in Tcl_GetReturnOptions by Tcl_AddErrorInfo(interp, "") with thrown error message...

So ultimately with this 3-way transfer (interp eval -> invocation of alias AliasLoad -> calling invokehidden) it would reach the calling interpreter with non-empty errorInfo (containing the error message only, without the callstack).

The wrong line within interp eval is therefore only an after effect of the bug in Tcl_GetReturnOptions. Thus fixed now in Tcl_GetReturnOptions, where it'd reset the errorLine if no errorInfo was initially thrown (before errorInfo becomes updated to error message).


sebres added on 2025-03-06 16:26:18:

Hmm, pity that I did not check the safe.test, but seeing @dgp amend [b756080dc6f8cd05], the whole fix looks a bit weird to me now, because there is no line 59 in code of interp eval (basically the evaluating scripts are single-line scripts).

If I do debug-logging from Tcl_TransferResult, it does that 3 times during test safe-10.4.1, for instance:

******** 04128CA8 ==> 014058B0 : 1 - can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
    while executing
"load {} Safepkg1 x"
******** 014058B0 ==> 04128CA8 : 59 - load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
******** 04128CA8 ==> 014058B0 : 1 - load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
    ("interp eval" body line 59)
    invoked from within
"load {} Safepkg1 x"

(where only middle has errorLine = 59, probably some old value that did not reset in-between)...

Anyway, this doesn't look correct to me. I'll fix it soon.


sebres added on 2025-03-06 14:36:16:

Since no objections, merged now in [f1d2397c7c640072]. Ticket closed as resolved.


sebres added on 2025-02-27 13:44:44:

Already answered on stackoverflow, however hereafter noticed that sometimes it may be indeed interesting, thus here is a fix [497e526e670a9faf] (done in minimalistic way)...

Reviews are welcome. If no objections follow I'll merge it at some point later.