Tcl Source Code

View Ticket
Login
Ticket UUID: e38dce74e28420b6c1f44fba604c4ed6193a6391
Title: Command line built with list not properly quoted
Type: Bug Version: 8.7
Submitter: sbron Created on: 2024-09-17 18:38:51
Subsystem: 17. Commands I-L Assigned To: apnadkarni
Priority: 5 Medium Severity: Important
Status: Open Last Modified: 2024-09-19 08:20:55
Resolution: None Closed By: nobody
    Closed on:
Description:

A command line built using the list command is not always quoted correctly. Example:

set cmd ##foo
set args {}
puts [list {*}$cmd {*}$args]

Result in 9.0.0: ##foo
Result in 8.6.14: {##foo}

This means that a command built like that will not be executed in 9.0.0 because it gets interpreted as a comment.

User Comments: sbron added on 2024-09-19 08:20:55:

Looking deeper into the issue, I find that the Tcl 8.6 code that handles this situation (Tcl_ListObjReplace()) contains the following comment:

    /*
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canonical form. This is important.
     * Resist any temptation to optimize this case.
     */
On Tcl 9.0 a different function is used (TclListObjAppendElements()), which does have the optimization that was warned against. Disabling the shortcut when elemCount <= 0 fixes the problem.


jan.nijtmans added on 2024-09-18 20:20:40:

So, doing a bisect:

  2 BAD     2024-09-18 15:43:29 9c8c6e1576248c08
  4 BAD     2023-03-19 11:56:58 2697657fd20c9270
  6 BAD     2022-10-28 13:51:18 57394eda0b9c91f1
  7 BAD     2022-09-12 11:10:49 e06d228ee0f6e848
  9 BAD     2022-08-30 06:53:35 6f3a9fb52414fda9
 12 BAD     2022-08-29 09:56:51 b8d47e9100fa4105
 13 BAD     2022-08-29 08:03:58 d9b720c46d3e8155
 14 GOOD    2022-08-26 23:11:44 a9db66657b33bf62 CURRENT
 11 GOOD    2022-08-26 22:50:50 c6af6c33818bf1e2
 10 GOOD    2022-08-23 06:37:37 2254d0416707f433
  8 GOOD    2022-07-25 14:05:59 ce8f522a49aef039
  5 GOOD    2022-06-20 09:44:07 f16233109c67e020
  3 GOOD    2021-03-30 10:17:09 d59e47d7c9c00eb4
  1 GOOD    2017-09-08 12:50:06 31bf3805809c5afe

This points the problem at [d9b720c46d3e8155|this] commit, which is the TIP #625 implementation: "Re-implementation of lists". I already suspected this before doing the bisect, just wanted to be sure ....

Therefore, assigning to Ashok


oehhar added on 2024-09-18 17:42:26:

Hi Schelte, Hi Jan, I did not know, that this is valid to name a command with leading "#". For me, the quoting for a list is ok. The following snippet returns ##foo for 8.6 and 9.0

proc {##foo} {args} {puts !}
set cmd ##foo
set args {}
set c [list {*}$cmd {*}$args]
lindex $c 0

IMHO it is "interesting" to include the special syntax of a command in a list quoting. The list behaves differently than "[]". Really interesting and amazing...

TCL 8.6 and 9.0 are identical here for me:

% proc {##cmd} {args} {puts !}
% ##cmd
% {##cmd}
!
% set cmd ##cmd
##cmd
% list $cmd
{##cmd}
% puts {*}$cmd
##cmd
% puts [{*}$cmd]
!

So, the [$cmd] with cmd = ##cmd calls the command - weired !

The use case by Schelte is, that a command would call the command in one case, but not in the other.

Ok, lets try:

proc {##foo} {args} {puts !}
set cmd ##foo
set args {}
set c [list {*}$cmd {*}$args]
lindex $c 0

On 8.6:

% eval $c
!
% puts [$c]
invalid command name "{##foo}"

On 9.0:

% eval $c
% puts [$c]
!

That is weired big fun !

Thank you for all, Harald


jan.nijtmans added on 2024-09-18 16:30:10:

Same problem in 8.7 too