From b33bd86d72135a55a373e14ee519fba519f5142d Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Mon, 8 Mar 2021 02:54:28 +0700 Subject: [PATCH] Fix `Parser` allowing parsed integer to overflow --- sources/Text/Parser.uc | 34 +++++++++++++++++++++++++++++- sources/Text/Tests/TEST_Parser.uc | Bin 110896 -> 113266 bytes 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/sources/Text/Parser.uc b/sources/Text/Parser.uc index 86a9265..f7a67d6 100644 --- a/sources/Text/Parser.uc +++ b/sources/Text/Parser.uc @@ -568,7 +568,9 @@ public final function Parser MUnsignedInteger( nextPosition = _.text.CharacterToInt(GetCharacter(), base); if (nextPosition < 0) break; - result = result * base + nextPosition; + // This `result = result * base + nextPosition`, + // but protected from integer overflow + result = SafeIntegerCombination(result, base, nextPosition); consumedCodePoints += 1; ShiftPointer(); } @@ -580,6 +582,36 @@ public final function Parser MUnsignedInteger( return self; } +/** + * Auxiliary method for a adding another numeric position `addition` to the + * given `baseValue` in base the `multiplier`, effectively performing: + * `baseValue * multiplier + addition`, but safely truncated at + * `MaxInt = 0x7fffffff`, preventing integer overflow. + * + * @param baseValue Initial value to modify by multiplication and addition. + * @param multiplier Value to first multiply given `baseValue` first. + * @param addition Value to add to the result of multiplication of + * `baseValue` and `multiplier`. + * @return `baseValue * multiplier + addition` truncated at + * `MaxInt = 0x7fffffff`, preventing integer overflow. + */ +protected final function int SafeIntegerCombination( + int baseValue, + int multiplier, + int addition) +{ + local int safeThreshold; + safeThreshold = MaxInt / multiplier; + if (baseValue > safeThreshold) { + return MaxInt; + } + baseValue *= multiplier; + if (MaxInt - baseValue < addition) { + return MaxInt; + } + return baseValue + addition; +} + /** * Parses escaped sequence of the type that is usually used in * string literals: backslash "\"", followed by any character diff --git a/sources/Text/Tests/TEST_Parser.uc b/sources/Text/Tests/TEST_Parser.uc index 75faa589d4a472d314416fafc02c5e2d15fe7a3e..37d2da96e1c223a9058a13b81b0d788e0143e66f 100644 GIT binary patch delta 607 zcmdn+i0#uCwuUW?$qv(d?HM)r{Ta#_QW=UE(in0W@)^n}FIb$seYXSS4e!bO>!hZy zw`XKSS2Eq9iSf6i5`!m09zzLGZ#r1N0#G-KNel`MnGD51G7l(I0;Dq-5`pX#pgpNT zQekp~yC`cpP&9KIJEQ32_kJRi=Vy5c8!;F%m@t?Fu?2%MgBggPzF;wlsf%@KVv*^8Zb8CaQeK(jPfAg>#-^T!^Uiy3u7Qg z5b&ol7$8Hq^YLjCG)LG1W+B21NgF5J>yr)kcuv;0=bC)}IoI_4^B8$1t2&BJj*nED OyuMao`|ln`QxyQA#h6b3 delta 31 pcmV+)0O0@f^ailv27t5yV?dLg>sq(}KmpcElP^CCx8IcklOzCW4%h$y