Modify

Opened 3 years ago

Last modified 2 years ago

#3972 assigned Bug

StringSplit can create invalid Arrays

Reported by: anonymous Owned by: Jon
Milestone: Component: AutoIt
Version: 3.3.16.1 Severity: None
Keywords: Cc:

Description

Global $s = ' '
For $i = 0 To 24 Step 1
        $s = $s & $s
Next
; String is now 33554432 symbols long

Global $a = StringSplit($s, '') ; Also works with flags 1, 2 and 3. If count is in [0], UBound correctly shows 33554433.
Global $err = @error, $ext = @extended
ConsoleWrite('@error = ' & $err & @CRLF) ; @error is not set, because delimiters were indeed found
ConsoleWrite('@extended = ' & $ext & @CRLF) ; Just to be sure it is also 0.
ConsoleWrite('VarGetType = ' & VarGetType($a) & @CRLF) ; It is an array
ConsoleWrite('UBound = ' & UBound($a) & @CRLF) ; UBound works (propably because Array-Metadata are set before the array is filled, I don't know the code so this is guesswork)
ConsoleWrite($a[0] & @CRLF) ; This will fail -> Array variable has incorrect number of subscripts or subscript dimension range exceeded

Attachments (0)

Change History (7)

comment:1 by Jos, 3 years ago

Guess a check for the second parameter would be appropriate to ensure it has a length of 1 or more.
The helpfile does state:
delimiters: One or more characters to use as delimiters (case sensitive).

Last edited 3 years ago by Jos (previous) (diff)

comment:2 by AspirinJunkie, 3 years ago

The help also states:
If you use an empty string "" for the delimiters, each character will be returned as an element.

I strongly suggest not touching this behavior. First, it would be script breaking for a lot of scripts that use StringSplit to split a string into an array of characters and second, it doesn't fix the bug described here, since it also occurs with a delimiter with one or more characters:

Global $s = ' '
For $i = 0 To 24 Step 1
        $s = $s & ";" & $s
Next
ConsoleWrite(StringLen($s) & @CRLF)
; String is now 33,554,432 symbols long with 33,554,431 delimiters

Global $a = StringSplit($s, ';') ; Also works with flags 1, 2 and 3. If count is in [0], UBound correctly shows 33554433.
Global $err = @error, $ext = @extended
ConsoleWrite('@error = ' & $err & @CRLF) ; @error is not set, because delimiters were indeed found
ConsoleWrite('@extended = ' & $ext & @CRLF) ; Just to be sure it is also 0.
ConsoleWrite('VarGetType = ' & VarGetType($a) & @CRLF) ; It is an array
ConsoleWrite('UBound = ' & UBound($a) & @CRLF) ; UBound works (propably because Array-Metadata are set before the array is filled, I don't know the code so this is guesswork)
ConsoleWrite($a[0] & @CRLF) ; This will fail -> Array variable has incorrect number of subscripts or subscript dimension range exceeded

The behavior also differs between AutoIt versions. Under version 3.14.5 the script crashes when StringSplit is called. I have not tested other versions.

comment:3 by Jos, 3 years ago

True... so something is broken.....

comment:4 by AspirinJunkie, 3 years ago

The problem is obviously that StringSplit would create an array with more elements than the maximum number of array elements possible in AutoIt (VAR_SUBSCRIPT_ELEMENTS = 16,777,216):

#include "String.au3"

$s = _StringRepeat(' ', 16777215) ; change to 16777216 to see the effect
Global $a = StringSplit($s, '')

ConsoleWrite(StringFormat("@error: %s\n@extended: %\nVargetType: %s\nUbound: %d\n", _
@error, @extended, VarGetType($a), UBound($a)))
ConsoleWrite($a[0] & @CRLF)

So basically all that is missing is another query in StringSplit that catches this case and then sets @error in it and returns either an empty array or a truncated array.

comment:5 by J-Paul Mesnage, 3 years ago

Owner: set to J-Paul Mesnage
Status: newassigned

Thanks Fix sent to Jon

comment:6 by jchd18, 2 years ago

See also ticket #3976 about the exact same issue with StringRegExp.

comment:7 by J-Paul Mesnage, 2 years ago

Owner: changed from J-Paul Mesnage to Jon

Modify Ticket

Action
as assigned The owner will remain Jon.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.