1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

math.big: fix internal subtract_align_last_byte_in_place overflow (#18413)

This commit is contained in:
phoebe 2023-06-12 12:33:53 +02:00 committed by GitHub
parent f73e99cddd
commit 37386697a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 23 deletions

View File

@ -124,29 +124,46 @@ fn test_mod() {
assert (big.integer_from_u64(7) % big.integer_from_u64(5)).int() == 2
}
fn test_divmod() {
x, y := big.integer_from_u64(13).div_mod(big.integer_from_u64(10))
assert x.int() == 1
assert y.int() == 3
p, q := big.integer_from_u64(13).div_mod(big.integer_from_u64(9))
assert p.int() == 1
assert q.int() == 4
c, d := big.integer_from_u64(7).div_mod(big.integer_from_u64(5))
assert c.int() == 1
assert d.int() == 2
x1 := big.integer_from_string('2103180314840157') or { panic('Cannot read decimal') }
y1 := big.integer_from_string('1631403814113') or { panic('Cannot read decimal') }
q0 := big.integer_from_int(1289)
r0 := big.integer_from_string('300798448500') or { panic('Cannot read decimal') }
q1, r1 := x1.div_mod(y1)
assert q1 == q0
assert r1 == r0
struct DivisionTest {
dividend string
divisor string
quotient string
remainder string
}
e := big.integer_from_string('21408410031413414147401') or { panic('Cannot read decimal') }
f := big.integer_from_string('3130541314113413') or { panic('Cannot read decimal') }
g, h := e.div_mod(f)
assert g.str() == '6838564'
assert h.str() == '2900204736088469'
const divmod_test_data = [
DivisionTest{'13', '10', '1', '3'},
DivisionTest{'13', '9', '1', '4'},
DivisionTest{'7', '5', '1', '2'},
DivisionTest{'2103180314840157', '1631403814113', '1289', '300798448500'},
DivisionTest{'21408410031413414147401', '3130541314113413', '6838564', '2900204736088469'}
// vfmt off
DivisionTest{
'13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096',
'13407807926845237209807376456131917626043958556151178674833163543294276330515137663421134775482798690129946803802212663956180562088664022929883876655300863',
'1',
'3097359889766648542073928501435407264441214702890397900427487699558409313380739522684104737560085054384273386897573320723282547016549772350783233',
},
DivisionTest{
'24388660549343689307666288436614463270948472382596516055139370678271628439810393042585576900667596857198513726355043536294702186342478937800831',
'38733748171303628844838787580045178098452927239062690602450784467058896912531690007767956310348951731921168881868406259712',
'629648864382619361826',
'2724578611525334851445652767465274410979805962941953382558409365935061481311529445551691298696266856092833571769883246719',
},
// vfmt on
]
fn test_divmod() {
for t in divmod_test_data {
a := big.integer_from_string(t.dividend) or { panic('Cannot read decimal') }
b := big.integer_from_string(t.divisor) or { panic('Cannot read decimal') }
eq := big.integer_from_string(t.quotient) or { panic('Cannot read decimal') }
er := big.integer_from_string(t.remainder) or { panic('Cannot read decimal') }
q, r := a.div_mod(b)
assert q == eq
assert r == er
}
}
fn test_comparison() {

View File

@ -1,5 +1,6 @@
module big
import math
import math.bits
// suppose operand_a bigger than operand_b and both not null.
@ -96,7 +97,8 @@ fn subtract_align_last_byte_in_place(mut a []u32, b []u32) {
mut new_carry := u32(0)
offset := a.len - b.len
for index := a.len - b.len; index < a.len; index++ {
if a[index] < (b[index - offset] + carry) {
if a[index] < (b[index - offset] + carry)
|| (b[index - offset] == math.max_u32 && carry > 0) {
new_carry = 1
} else {
new_carry = 0