View Ticket
Not logged in
Ticket UUID: d07f42998da94cfe0c9cebc73c5cecc63f99f421
Title: Tcl_CreateObjCommand2 argument truncation and misleading error message
Type: Bug Version: 9.0
Submitter: apnadkarni Created on: 2023-04-30 07:56:37
Subsystem: - New Builtin Commands Assigned To: apnadkarni
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2023-06-29 16:09:57
Resolution: Fixed Closed By: apnadkarni
    Closed on: 2023-06-29 16:09:57
Description:
The new Tcl_CreateObjCommand2 API permits creation of commands which accept more than `2**31` arguments. The following anomalous behavior is seen.

When called through the 8.x wrapper, argument count wraps around. Instead, an error should be raised.

```
% set cmd [testbigdata list 0x100000008]; llength $cmd
4294967304
% ledit cmd 0 0 testcmdobj2 ; llength $cmd
4294967304
% testcmdinfo call $cmd
8 1 7
```

`testcmdobj2` uses the Tcl_CreateObjCommand2 API to register itself and accepts ptrdiff_t sized counts. Its return is objc, first and last argument. As seen above, 0x100000008 is wraps around to 8. An error should be raised instead.

Conversely, an old style command (e.g. lappend) also truncates when called through the new or old API when called with more than 2**32 arguments.

```
% set l [testbigdata list 0x100000008]; llength $l
4294967304
% ledit l 0 1 lappend x ; llength $l
4294967304
% testcmdinfo call $l
2 3 4 5 6 7
% unset x
% testcmdinfo call2 $l
2 3 4 5 6 7
```

When called with objc between INT_MAX and UINT_MAX, it does give an error but a misleading one.

```
% set cmd [testbigdata list 0x80000008]; llength $cmd
2147483656
% ledit cmd 0 1 lappend X ; llength $cmd
2147483656
% testcmdinfo call $cmd
wrong # args: should be "lappend varName ?value ...?"
% testcmdinfo call2 $cmd
wrong # args: should be "lappend varName ?value ...?"
```

This error message, while not entirely wrong, is misleading and confusing since the error message text for lappend seems to indicate any number of arguments are accepted. A more informative error would be one that states that max argument count exceeded.
User Comments: apnadkarni added on 2023-05-09 17:27:30:
With respect to call vs call2 - That is by intent. The purpose of the testcmdinfo is to test the exact C API by calling the underlying C functions without any argument checks. When the "Call" interface is used, the C API by definition cannot pass more than INT_MAX arguments (or negative ones). testcmdinfo does not check for that as a test command it expects the caller (test script) to pass arguments that match the type of the C API. Like much of the test framework, it does not check for errors on the part of the script. One can add that check to the implementation of testcmdinfo if one wishes, not to the core code.

In other words, with the call command which maps to the 8.6 "int" based interfaces, it is impossible to pass more than INT_MAX arguments. You can pass negative objc (between INT_MAX and UINT_MAX) values which results in the wrong # args message. You cannot pass > INT_MAX positive values which result in "limit exceeded

/Ashok

/Ashok

jan.nijtmans added on 2023-05-09 16:48:56:

Trying now:

% set cmd [testbigdata list 0x80000008]; llength $cmd
2147483656
% ledit cmd 0 1 lappend X ; llength $cmd
2147483656
% testcmdinfo call $cmd
wrong # args: should be "lappend varName ?value ...?"
% testcmdinfo call2 $cmd
Number of words (2147483656) in command exceeds limit 2147483647.
% eval $cmd
wrong # args: should be "lappend varName ?value ...?"

So "lappend" cannot handle so many arguments. But why do the error-messages differ between "call" and "call2"? Isn't "eval" the same as "testcmdinfo call"? I still see the old error-message there


apnadkarni added on 2023-05-01 11:43:49:
Fixed in [71cab27557]

apnadkarni added on 2023-04-30 08:10:10:
Working on a proposed fix in [bug-d07f42998d].