Menu

#729 Fixed-length string concat + assign misoptimization

open
nobody
None
compiler
2015-01-29
2014-05-23
dkl
No

fbc optimizes string assignment + concatenation, for example:

    a = b + c + d     assign(a, concat(concat(b, c), d))
becomes:
    a = b             assign(a, b)
    a += c            concatassign(a, c)
    a += d            concatassign(a, d)

If a is a fixed-length string, appending c & d requires determining a's current length, which is done by searching for the null terminator.

The problem is that in case b contained null bytes, the first of those will become a's null terminator, and following string appends will start at the wrong offset.

'' Assigning to dynamic string:
''    dynstr  = chr(&hAA) + chr(0) + chr(&hBB)
'' becomes:
''    dynstr  = chr(&hAA)     AA 00
''    dynstr += chr(0)        AA 00 00
''    dynstr += chr(&hBB)     AA 00 BB 00  ok.
''
'' Assigning to fixed-length string:
''    fixstr  = chr(&hAA) + chr(0) + chr(&hBB)
'' becomes:
''    fixstr  = chr(&hAA)     AA 00
''    fixstr += chr(0)        AA 00 (or maybe AA 00 00, doesn't matter)
''    fixstr += chr(&hBB)     AA BB 00  appended at first null,
''                                      since the real length isn't
''                                      stored anywhere - visibly
''                                      different result.

#macro dumpBytes( s, size )
    scope
        var p = cptr(ubyte ptr, (s))
        for i as integer = 0 to (size)-1
            print " ";hex( p[i], 2 );
        next
        print
    end scope
#endmacro

print "assigning chr()+chr()+... to  STRING    :";
dim s as string
s = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
dumpBytes(strptr(s), len(s)+1)

scope
    print "assigning chr()+chr()+... to  STRING * N:";
    dim s as string * 5
    s = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
    dumpBytes(@s, 5+1)
end scope

scope
    print "assigning string variable to  STRING * N:";
    dim fs as string * 5
    fs = s
    dumpBytes(@fs, 5+1)
end scope

scope
    print "assigning chr()+chr()+... to ZSTRING * N:";
    dim z as zstring * 5+1
    z = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
    dumpBytes(@z, 5+1)
end scope

scope
    print "assigning string variable to ZSTRING * N:";
    dim z as zstring * 5+1
    z = s
    dumpBytes(@z, 5+1)
end scope

I.e. the optimization can cause visible differences. This wouldn't happen if the strings were appended in the non-optimized form, because there normal dynamic strings would be used which are capable of handling embedded nulls.

Related

Bugs: #966

Discussion


Log in to post a comment.

MongoDB Logo MongoDB