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
|
# 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
|
# raises a LSLCantCompute exception that is caught by the optimizer to leave
|
||||||
# the expression unchanged. For example, llBase64ToInteger("AA") returns
|
# the expression unchanged. For example, llXorBase64Strings has a delay, so it
|
||||||
# unpredictable garbage in the low bytes in LSL, so it is left unchanged.
|
# 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.
|
# The JSON functions have been separated to their own module.
|
||||||
|
|
||||||
|
@ -993,8 +994,6 @@ def llAxisAngle2Rot(axis, angle):
|
||||||
s = math.sin(angle*0.5)
|
s = math.sin(angle*0.5)
|
||||||
return Quaternion(F32((axis[0]*s, axis[1]*s, axis[2]*s, c)))
|
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):
|
def llBase64ToInteger(s):
|
||||||
s = fs(s)
|
s = fs(s)
|
||||||
if len(s) > 8:
|
if len(s) > 8:
|
||||||
|
@ -1002,14 +1001,11 @@ def llBase64ToInteger(s):
|
||||||
s = b64_re.search(s).group()
|
s = b64_re.search(s).group()
|
||||||
i = len(s)
|
i = len(s)
|
||||||
s = b64decode(s + u'='*(-i & 3))
|
s = b64decode(s + u'='*(-i & 3))
|
||||||
if len(s) < 3:
|
s = bytearray(s + b'\0\0\0\0')[:4]
|
||||||
# not computable deterministically
|
|
||||||
raise ELSLCantCompute
|
|
||||||
s = bytearray(s + b'\0')[:4]
|
|
||||||
i = s[0] if s[0] < 128 else s[0]-256
|
i = s[0] if s[0] < 128 else s[0]-256
|
||||||
return (i<<24)+(s[1]<<16)+(s[2]<<8)+s[3]
|
return (i<<24)+(s[1]<<16)+(s[2]<<8)+s[3]
|
||||||
|
|
||||||
b64tos_re = re.compile(
|
b64tostr_re = re.compile(
|
||||||
b'('
|
b'('
|
||||||
# Those pass through and are caught by InternalUTF8toString:
|
# Those pass through and are caught by InternalUTF8toString:
|
||||||
b'\x00$' # NUL at last position (zstr removes it)
|
b'\x00$' # NUL at last position (zstr removes it)
|
||||||
|
@ -1052,9 +1048,9 @@ def llBase64ToString(s):
|
||||||
byteseq = bytearray(b64decode(s + u'=' * (-len(s) & 3)))
|
byteseq = bytearray(b64decode(s + u'=' * (-len(s) & 3)))
|
||||||
|
|
||||||
pos = 0
|
pos = 0
|
||||||
match = b64tos_re.search(byteseq, pos)
|
match = b64tostr_re.search(byteseq, pos)
|
||||||
while match is not None:
|
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 '')
|
L = len(match.group(2) or '')
|
||||||
if L:
|
if L:
|
||||||
byteseq[pos:pos+L] = b'?'
|
byteseq[pos:pos+L] = b'?'
|
||||||
|
@ -1062,7 +1058,7 @@ def llBase64ToString(s):
|
||||||
else:
|
else:
|
||||||
pos = match.end(1)
|
pos = match.end(1)
|
||||||
|
|
||||||
match = b64tos_re.search(byteseq, pos)
|
match = b64tostr_re.search(byteseq, pos)
|
||||||
|
|
||||||
return InternalUTF8toString(byteseq)
|
return InternalUTF8toString(byteseq)
|
||||||
|
|
||||||
|
@ -1917,10 +1913,6 @@ def llXorBase64(s, xor):
|
||||||
|
|
||||||
if L2 == 0:
|
if L2 == 0:
|
||||||
# The input xor string starts with zero or one valid Base64 characters.
|
# 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
|
L2 = 2
|
||||||
xor = u'AA'
|
xor = u'AA'
|
||||||
|
|
||||||
|
@ -1932,10 +1924,12 @@ def llXorBase64(s, xor):
|
||||||
ret = bytearray(b'')
|
ret = bytearray(b'')
|
||||||
|
|
||||||
Bug3763 = 3763 in Bugs
|
Bug3763 = 3763 in Bugs
|
||||||
# BUG-3763 consists of the binary string having an extra NULL every time after the second repetition of
|
# BUG-3763 consists of the binary string having an extra NULL every time
|
||||||
# the XOR pattern. For example, if the XOR binary string is b'pqr' and the input string is
|
# after the second repetition of the XOR pattern. For example, if the XOR
|
||||||
# b'12345678901234567890', the XOR binary string behaves as if it was b'pqrpqr\0pqr\0pqr\0pqr\0pq'.
|
# binary string is b'pqr' and the input string is b'12345678901234567890',
|
||||||
# We emulate that by adding the zero and increasing the length the first time.
|
# 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:
|
for c in s:
|
||||||
ret.append(c ^ xor[i])
|
ret.append(c ^ xor[i])
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -2007,10 +2001,6 @@ def llXorBase64StringsCorrect(s, xor):
|
||||||
|
|
||||||
if L2 == 0:
|
if L2 == 0:
|
||||||
# The input xor string starts with zero or one valid Base64 characters.
|
# 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
|
L2 = 2
|
||||||
xor = u'AA'
|
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)
|
, llGetDisplayName(TEXTURE_BLANK)
|
||||||
, llGetEnv("estate_name")
|
, llGetEnv("estate_name")
|
||||||
, llXorBase64Strings("++++", "?")
|
, llXorBase64Strings("++++", "?")
|
||||||
, llXorBase64StringsCorrect("++++", "?")
|
|
||||||
, llXorBase64("++++", "?")
|
|
||||||
, llBase64ToInteger("ABC")
|
|
||||||
, llAbs(-2147483648)
|
, llAbs(-2147483648)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,6 @@ default
|
||||||
, llGetDisplayName("5748decc-f629-461c-9a36-a35a221fe21f")
|
, llGetDisplayName("5748decc-f629-461c-9a36-a35a221fe21f")
|
||||||
, llGetEnv("estate_name")
|
, llGetEnv("estate_name")
|
||||||
, llXorBase64Strings("++++", "?")
|
, llXorBase64Strings("++++", "?")
|
||||||
, llXorBase64StringsCorrect("++++", "?")
|
|
||||||
, llXorBase64("++++", "?")
|
|
||||||
, llBase64ToInteger("ABC")
|
|
||||||
, llAbs(((integer)-2147483648))
|
, llAbs(((integer)-2147483648))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue