Panic within `QUICRandomFrames`
Hey,
This is a great library, however there seems to be an issue with the QUICRandomFrames algorithm I am sometimes running into. It throws: panic: crypto/rand: argument to Int is <= 0
Based on the stacktrace it occurs at this line:
https://github.com/refraction-networking/uquic/blob/98f5a5debca432d7ce82f048846283a3370da17a/u_quic_frames.go#L253
I modified the surrounding code blindly to avoid overflows:
lenCryptoData := uint64(len(cryptoData))
offsetCryptoData := uint64(0)
for i := uint64(0); i < numCRYPTO-1; i++ { // select n-1 times, since the last one must be the remaining
// randomly select length of CRYPTO frame.
// Length must be at least 1 byte and at most the remaining length of cryptoData minus the remaining number of CRYPTO frames.
// i.e. len in [1, len(cryptoData)-offsetCryptoData-(numCRYPTO-i-2))
log.Printf("lenCryptoData: %d, offsetCryptoData: %d, numCRYPTO: %d, i: %d\n", lenCryptoData, offsetCryptoData, numCRYPTO, i)
remainingCrypto := lenCryptoData - (numCRYPTO - i - 2)
// check if it overflows uint64
if remainingCrypto > 0xFFFFFFFF || remainingCrypto == 0 {
log.Printf("remainingCrypto overflow: %d\n", remainingCrypto)
break
} else {
log.Printf("remainingCrypto: %d\n", remainingCrypto)
}
lenCRYPTO, err := cryptoSafeRandUint64(1, remainingCrypto)
if err != nil {
return nil, err
}
frameList = append(frameList, QUICFrameCrypto{Offset: int(offsetCryptoData), Length: int(lenCRYPTO)})
offsetCryptoData += lenCRYPTO
lenCryptoData -= lenCRYPTO
}
And in the problematic case I saw this in the logs:
2024/12/20 03:59:19 lenCryptoData: 508, offsetCryptoData: 0, numCRYPTO: 5, i: 0
2024/12/20 03:59:19 remainingCrypto: 505
2024/12/20 03:59:19 lenCryptoData: 69, offsetCryptoData: 439, numCRYPTO: 5, i: 1
2024/12/20 03:59:19 remainingCrypto: 67
2024/12/20 03:59:19 lenCryptoData: 54, offsetCryptoData: 454, numCRYPTO: 5, i: 2
2024/12/20 03:59:19 remainingCrypto: 53
2024/12/20 03:59:19 lenCryptoData: 31, offsetCryptoData: 477, numCRYPTO: 5, i: 3
2024/12/20 03:59:19 remainingCrypto: 31
2024/12/20 03:59:19 lenCryptoData: 0, offsetCryptoData: 0, numCRYPTO: 6, i: 0
2024/12/20 03:59:19 remainingCrypto overflow: 18446744073709551612
It doesn't always happen, but when it does, the program panics...
Wait I just realized that this is a different issue from the PR above 🤦
panic: crypto/rand: argument to Int is <= 0
goroutine 71 [running]: crypto/rand.Int({0x104a53ce0?, 0x1400012a2e0?}, 0x140001836b8?) /usr/local/go/src/crypto/rand/util.go:69 +0x288 github.com/refraction-networking/uquic.(*QUICRandomFrames).Build.func1(...) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_quic_frames.go:214 github.com/refraction-networking/uquic.(*QUICRandomFrames).Build(0x140000cda90, {0x0, 0x0, 0x0}) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_quic_frames.go:244 +0x4dc github.com/refraction-networking/uquic.(*uPacketPacker).MarshalInitialPacketPayload(0x140000a91a0, {{0x0, 0x0, 0x0}, {0x140005728e0, 0x1, 0x1}, 0x140000b9540, 0x6}, 0x1) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_packet_packer.go:257 +0x178 github.com/refraction-networking/uquic.(*uPacketPacker).appendInitialPacket(0x140000a91a0, 0x14000572900, 0x140000bb380, {{0x0, 0x0, 0x0}, {0x140005728e0, 0x1, 0x1}, 0x140000b9540, ...}, ...) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_packet_packer.go:174 +0x80 github.com/refraction-networking/uquic.(*uPacketPacker).MaybePackProbePacket(0x140000a91a0, 0x1, 0x4e4, 0x1) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_packet_packer.go:318 +0x914 github.com/refraction-networking/uquic.(*connection).sendProbePacket(0x1400051e908, 0x1, {0x14000183bd8?, 0x1050a8be0?, 0x1050a8be0?}) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/connection.go:2039 +0x124 github.com/refraction-networking/uquic.(*connection).triggerSending(0x1400051e908, {0xd54abf8d?, 0x1050a8be0?, 0x1050a8be0?}) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/connection.go:1808 +0x98 github.com/refraction-networking/uquic.(*connection).run(0x1400051e908) /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/connection.go:640 +0x790 github.com/refraction-networking/uquic.(*uClient).dial.func1() /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_client.go:113 +0x44 created by github.com/refraction-networking/uquic.(*uClient).dial in goroutine 66 /Users/zhaoxiaoxiao/go/pkg/mod/github.com/refraction-networking/[email protected]/u_client.go:112 +0x494