Fix empty path crash issue for MultiAddresses `unix`, `ip6zone`, `dns***`. (#1025)

This issue was discovered by @0xTylerHolmes . Thank you!
This commit is contained in:
Eugene Kabanov 2024-02-22 16:57:11 +02:00 committed by GitHub
parent 349496e40f
commit fec632d28d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 91 additions and 39 deletions

View File

@ -119,23 +119,46 @@ proc ip6VB(vb: var VBuffer): bool =
if vb.readArray(a.address_v6) == 16:
result = true
proc ip6zoneStB(s: string, vb: var VBuffer): bool =
## IPv6 stringToBuffer() implementation.
template pathStringToBuffer(s: string, vb: var VBuffer): bool =
if len(s) > 0:
vb.writeSeq(s)
result = true
true
else:
false
template pathBufferToString(vb: var VBuffer, s: var string): bool =
s = ""
if (vb.readSeq(s) > 0) and (len(s) > 0):
true
else:
false
template pathBufferToStringNoSlash(vb: var VBuffer, s: var string): bool =
s = ""
if (vb.readSeq(s) > 0) and (len(s) > 0) and (s.find('/') == -1):
true
else:
false
template pathValidateBuffer(vb: var VBuffer): bool =
var s = ""
pathBufferToString(vb, s)
template pathValidateBufferNoSlash(vb: var VBuffer): bool =
var s = ""
pathBufferToStringNoSlash(vb, s)
proc ip6zoneStB(s: string, vb: var VBuffer): bool =
## IPv6 stringToBuffer() implementation.
pathStringToBuffer(s, vb)
proc ip6zoneBtS(vb: var VBuffer, s: var string): bool =
## IPv6 bufferToString() implementation.
if vb.readSeq(s) > 0:
result = true
pathBufferToStringNoSlash(vb, s)
proc ip6zoneVB(vb: var VBuffer): bool =
## IPv6 validateBuffer() implementation.
var s = ""
if vb.readSeq(s) > 0:
if s.find('/') == -1:
result = true
pathValidateBufferNoSlash(vb)
proc portStB(s: string, vb: var VBuffer): bool =
## Port number stringToBuffer() implementation.
@ -154,7 +177,8 @@ proc portBtS(vb: var VBuffer, s: var string): bool =
## Port number bufferToString() implementation.
var port: array[2, byte]
if vb.readArray(port) == 2:
var nport = (safeConvert[uint16](port[0]) shl 8) or safeConvert[uint16](port[1])
let nport =
(safeConvert[uint16](port[0]) shl 8) or safeConvert[uint16](port[1])
s = $nport
result = true
@ -214,7 +238,8 @@ proc onionBtS(vb: var VBuffer, s: var string): bool =
## ONION address bufferToString() implementation.
var buf: array[12, byte]
if vb.readArray(buf) == 12:
var nport = (safeConvert[uint16](buf[10]) shl 8) or safeConvert[uint16](buf[11])
let nport =
(safeConvert[uint16](buf[10]) shl 8) or safeConvert[uint16](buf[11])
s = Base32Lower.encode(buf.toOpenArray(0, 9))
s.add(":")
s.add($nport)
@ -248,7 +273,8 @@ proc onion3BtS(vb: var VBuffer, s: var string): bool =
## ONION address bufferToString() implementation.
var buf: array[37, byte]
if vb.readArray(buf) == 37:
var nport = (safeConvert[uint16](buf[35]) shl 8) or safeConvert[uint16](buf[36])
var nport =
(safeConvert[uint16](buf[35]) shl 8) or safeConvert[uint16](buf[36])
s = Base32Lower.encode(buf.toOpenArray(0, 34))
s.add(":")
s.add($nport)
@ -262,40 +288,27 @@ proc onion3VB(vb: var VBuffer): bool =
proc unixStB(s: string, vb: var VBuffer): bool =
## Unix socket name stringToBuffer() implementation.
if len(s) > 0:
vb.writeSeq(s)
result = true
pathStringToBuffer(s, vb)
proc unixBtS(vb: var VBuffer, s: var string): bool =
## Unix socket name bufferToString() implementation.
s = ""
if vb.readSeq(s) > 0:
result = true
pathBufferToString(vb, s)
proc unixVB(vb: var VBuffer): bool =
## Unix socket name validateBuffer() implementation.
var s = ""
if vb.readSeq(s) > 0:
result = true
pathValidateBuffer(vb)
proc dnsStB(s: string, vb: var VBuffer): bool =
## DNS name stringToBuffer() implementation.
if len(s) > 0:
vb.writeSeq(s)
result = true
pathStringToBuffer(s, vb)
proc dnsBtS(vb: var VBuffer, s: var string): bool =
## DNS name bufferToString() implementation.
s = ""
if vb.readSeq(s) > 0:
result = true
pathBufferToStringNoSlash(vb, s)
proc dnsVB(vb: var VBuffer): bool =
## DNS name validateBuffer() implementation.
var s = ""
if vb.readSeq(s) > 0:
if s.find('/') == -1:
result = true
pathValidateBufferNoSlash(vb)
proc mapEq*(codec: string): MaPattern =
## ``Equal`` operator for pattern
@ -660,7 +673,8 @@ proc getPart(ma: MultiAddress, index: int): MaResult[MultiAddress] =
inc(offset)
ok(res)
proc getParts[U, V](ma: MultiAddress, slice: HSlice[U, V]): MaResult[MultiAddress] =
proc getParts[U, V](ma: MultiAddress,
slice: HSlice[U, V]): MaResult[MultiAddress] =
when slice.a is BackwardsIndex or slice.b is BackwardsIndex:
let maLength = ? len(ma)
template normalizeIndex(index): int =
@ -674,7 +688,8 @@ proc getParts[U, V](ma: MultiAddress, slice: HSlice[U, V]): MaResult[MultiAddres
? res.append(? ma[i])
ok(res)
proc `[]`*(ma: MultiAddress, i: int | BackwardsIndex): MaResult[MultiAddress] {.inline.} =
proc `[]`*(ma: MultiAddress,
i: int | BackwardsIndex): MaResult[MultiAddress] {.inline.} =
## Returns part with index ``i`` of MultiAddress ``ma``.
when i is BackwardsIndex:
let maLength = ? len(ma)
@ -769,7 +784,7 @@ proc toString*(value: MultiAddress): MaResult[string] =
if not proto.coder.bufferToString(vb.data, part):
return err("multiaddress: Decoding protocol error")
parts.add($(proto.mcodec))
if proto.kind == Path and part[0] == '/':
if len(part) > 0 and (proto.kind == Path) and (part[0] == '/'):
parts.add(part[1..^1])
else:
parts.add(part)
@ -1120,16 +1135,20 @@ proc getField*(pb: ProtoBuffer, field: int,
if not(res):
ok(false)
else:
value = MultiAddress.init(buffer).valueOr: return err(ProtoError.IncorrectBlob)
value = MultiAddress.init(buffer).valueOr:
return err(ProtoError.IncorrectBlob)
ok(true)
proc getRepeatedField*(pb: ProtoBuffer, field: int,
value: var seq[MultiAddress]): ProtoResult[bool] {.
inline.} =
## Read repeated field from protobuf message. ``field`` is field number. If the message is malformed, an error is returned.
## If field is not present in message, then ``ok(false)`` is returned and value is empty. If field is present,
## but no items could be parsed, then ``err(ProtoError.IncorrectBlob)`` is returned and value is empty.
## If field is present and some item could be parsed, then ``true`` is returned and value contains the parsed values.
## Read repeated field from protobuf message. ``field`` is field number.
## If the message is malformed, an error is returned. If field is not present
## in message, then ``ok(false)`` is returned and value is empty. If field is
## present, but no items could be parsed, then
## ``err(ProtoError.IncorrectBlob)`` is returned and value is empty.
## If field is present and some item could be parsed, then ``true`` is
## returned and value contains the parsed values.
var items: seq[seq[byte]]
value.setLen(0)
let res = ? pb.getRepeatedField(field, items)

View File

@ -307,6 +307,29 @@ const
)
]
ZeroPathFailureVectors = [
"900300", # /unix//
"2A00", # /ip6zone//
"3800", # /dnsaddr//
"3600", # /dns4//
"3700", # /dns6//
]
CrashesVectors = [
"0401020304060050900366",
"2926013880ffffff2a040402030406005090030404020304060150900350900302030406005090030c2f383838383838383838383838383838382a",
"04010103042a040101030406005090030c",
"bd03afadec040bc547f9658668b1ff00000073001f101a37f54cc07fb4bc03bc039a18fbee063690033838383838383838383838383838383838383838383838383838383838",
"2a040402030406005090030406ffff",
"29260100094f81800e0000003880ffffff2a0404020304060050900304040203040404020304060050900304040203040601509003509003020406",
"38060606383838380606060600802a2438380606060600802a047f0000012a163c803c3c3c0606060680ffff002a0404020304380600509003040402030406015090035e2a2a2a2a2a2a2a2a",
"38060606060606060606060600802a2a2a047f0000012a063c803c3c3c383838012a063c80385fffffff2a260402030406005090030404020304060150900350",
"a503220000000000000000000000000000000002003880ffffff2a040402030406005090030404020304060150900350900302030406005090030c",
"047f0000012a2a2a2a2a2a2a2a2a2a2a2a2a2a2a062a2a042a8000142a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a50900350900302030406005090030c2f622f00000203040600030406005090030c2f612f2a712f63030406005090030c2f612f2a622f632a2a002a2a2a2a2a2a372a",
"047f000001062a2a042a8000142a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2ad52a2a2a2a2a2a2a2a2a2a50900350900302030406005090030c2f622f00000203040600030406005090030c2f612f2a622f63030406005090030c2f612f2a622f632a2a002a2a2a2a2a2a37d52a2a2a2a2a2a2a2a2a2a5090032a",
"90030c2a04"
]
suite "MultiAddress test suite":
test "go-multiaddr success test vectors":
@ -461,3 +484,13 @@ suite "MultiAddress test suite":
let error = pb.getRepeatedField(1, decoded).error()
check error == ProtoError.IncorrectBlob
check decoded.len == 0
test "MultiAddress with empty path test":
for item in ZeroPathFailureVectors:
let res = MultiAddress.init(hexToSeqByte(item))
check res.isErr()
test "MultiAddress crash test":
for item in CrashesVectors:
let res = MultiAddress.init(hexToSeqByte(item))
check res.isErr()