mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 15:48:21 +00:00
The Base64 functions that used to produce garbage no longer do
This commit is contained in:
parent
b6a5e01ed4
commit
53e8bd659a
6 changed files with 35 additions and 30 deletions
|
@ -28,8 +28,9 @@
|
|||
#
|
||||
# In some instances, the result can't be computed; in these cases the function
|
||||
# raises a LSLCantCompute exception that is caught by the optimizer to leave
|
||||
# the expression unchanged. For example, llBase64ToInteger("AA") returns
|
||||
# unpredictable garbage in the low bytes in LSL, so it is left unchanged.
|
||||
# the expression unchanged. For example, llXorBase64Strings has a delay, so it
|
||||
# can't just be replaced by its value; llFrand produces unpredictable results
|
||||
# (by design) in most cases, but not all.
|
||||
#
|
||||
# The JSON functions have been separated to their own module.
|
||||
|
||||
|
@ -993,8 +994,6 @@ def llAxisAngle2Rot(axis, angle):
|
|||
s = math.sin(angle*0.5)
|
||||
return Quaternion(F32((axis[0]*s, axis[1]*s, axis[2]*s, c)))
|
||||
|
||||
# NOTE: This one does not always return the same value in LSL. When it isn't
|
||||
# deterministic, it raises ELSLCantCompute.
|
||||
def llBase64ToInteger(s):
|
||||
s = fs(s)
|
||||
if len(s) > 8:
|
||||
|
@ -1002,14 +1001,11 @@ def llBase64ToInteger(s):
|
|||
s = b64_re.search(s).group()
|
||||
i = len(s)
|
||||
s = b64decode(s + u'='*(-i & 3))
|
||||
if len(s) < 3:
|
||||
# not computable deterministically
|
||||
raise ELSLCantCompute
|
||||
s = bytearray(s + b'\0')[:4]
|
||||
s = bytearray(s + b'\0\0\0\0')[:4]
|
||||
i = s[0] if s[0] < 128 else s[0]-256
|
||||
return (i<<24)+(s[1]<<16)+(s[2]<<8)+s[3]
|
||||
|
||||
b64tos_re = re.compile(
|
||||
b64tostr_re = re.compile(
|
||||
b'('
|
||||
# Those pass through and are caught by InternalUTF8toString:
|
||||
b'\x00$' # NUL at last position (zstr removes it)
|
||||
|
@ -1052,9 +1048,9 @@ def llBase64ToString(s):
|
|||
byteseq = bytearray(b64decode(s + u'=' * (-len(s) & 3)))
|
||||
|
||||
pos = 0
|
||||
match = b64tos_re.search(byteseq, pos)
|
||||
match = b64tostr_re.search(byteseq, pos)
|
||||
while match is not None:
|
||||
assert match.group(3) is None, 'Fail in b64tos_re: ' + match.group(3)
|
||||
assert match.group(3) is None, 'Fail in b64tostr_re: ' + match.group(3)
|
||||
L = len(match.group(2) or '')
|
||||
if L:
|
||||
byteseq[pos:pos+L] = b'?'
|
||||
|
@ -1062,7 +1058,7 @@ def llBase64ToString(s):
|
|||
else:
|
||||
pos = match.end(1)
|
||||
|
||||
match = b64tos_re.search(byteseq, pos)
|
||||
match = b64tostr_re.search(byteseq, pos)
|
||||
|
||||
return InternalUTF8toString(byteseq)
|
||||
|
||||
|
@ -1917,10 +1913,6 @@ def llXorBase64(s, xor):
|
|||
|
||||
if L2 == 0:
|
||||
# The input xor string starts with zero or one valid Base64 characters.
|
||||
# This produces garbage bytes (the first byte is zero though).
|
||||
if L1 > 2:
|
||||
# We don't produce a result in this case.
|
||||
raise ELSLCantCompute
|
||||
L2 = 2
|
||||
xor = u'AA'
|
||||
|
||||
|
@ -1932,10 +1924,12 @@ def llXorBase64(s, xor):
|
|||
ret = bytearray(b'')
|
||||
|
||||
Bug3763 = 3763 in Bugs
|
||||
# BUG-3763 consists of the binary string having an extra NULL every time after the second repetition of
|
||||
# the XOR pattern. For example, if the XOR binary string is b'pqr' and the input string is
|
||||
# b'12345678901234567890', the XOR binary string behaves as if it was b'pqrpqr\0pqr\0pqr\0pqr\0pq'.
|
||||
# We emulate that by adding the zero and increasing the length the first time.
|
||||
# BUG-3763 consists of the binary string having an extra NULL every time
|
||||
# after the second repetition of the XOR pattern. For example, if the XOR
|
||||
# binary string is b'pqr' and the input string is b'12345678901234567890',
|
||||
# the XOR binary string behaves as if it was b'pqrpqr\0pqr\0pqr\0pqr\0pq'.
|
||||
# We emulate that by adding the zero and increasing the length the first
|
||||
# time.
|
||||
for c in s:
|
||||
ret.append(c ^ xor[i])
|
||||
i += 1
|
||||
|
@ -2007,10 +2001,6 @@ def llXorBase64StringsCorrect(s, xor):
|
|||
|
||||
if L2 == 0:
|
||||
# The input xor string starts with zero or one valid Base64 characters.
|
||||
# This produces garbage bytes (the first byte is zero though).
|
||||
if L1 > 2:
|
||||
# We don't produce a result in this case.
|
||||
raise ELSLCantCompute
|
||||
L2 = 2
|
||||
xor = u'AA'
|
||||
|
||||
|
|
13
unit_tests/regression.suite/fixed-b64.lsl
Normal file
13
unit_tests/regression.suite/fixed-b64.lsl
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Some Base64 functions used to return garbage, now they no longer do
|
||||
default
|
||||
{
|
||||
timer()
|
||||
{
|
||||
llSetPrimitiveParams( // we need a function that causes side effects,
|
||||
// so that it isn't optimized out
|
||||
[ llXorBase64StringsCorrect("++++", "?")
|
||||
, llXorBase64("++++", "?")
|
||||
, llBase64ToInteger("ABC")
|
||||
]);
|
||||
}
|
||||
}
|
7
unit_tests/regression.suite/fixed-b64.out
Normal file
7
unit_tests/regression.suite/fixed-b64.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
default
|
||||
{
|
||||
timer()
|
||||
{
|
||||
llSetPrimitiveParams((list)"++++" + "++++" + 1048576);
|
||||
}
|
||||
}
|
1
unit_tests/regression.suite/fixed-b64.run
Normal file
1
unit_tests/regression.suite/fixed-b64.run
Normal file
|
@ -0,0 +1 @@
|
|||
main.py -y -O -dcr,-optfloats -
|
|
@ -22,9 +22,6 @@ default
|
|||
, llGetDisplayName(TEXTURE_BLANK)
|
||||
, llGetEnv("estate_name")
|
||||
, llXorBase64Strings("++++", "?")
|
||||
, llXorBase64StringsCorrect("++++", "?")
|
||||
, llXorBase64("++++", "?")
|
||||
, llBase64ToInteger("ABC")
|
||||
, llAbs(-2147483648)
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -20,9 +20,6 @@ default
|
|||
, llGetDisplayName("5748decc-f629-461c-9a36-a35a221fe21f")
|
||||
, llGetEnv("estate_name")
|
||||
, llXorBase64Strings("++++", "?")
|
||||
, llXorBase64StringsCorrect("++++", "?")
|
||||
, llXorBase64("++++", "?")
|
||||
, llBase64ToInteger("ABC")
|
||||
, llAbs(((integer)-2147483648))
|
||||
]);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue