Skip to content

Commit 9299517

Browse files
ahmedcharlesrjzak
authored andcommitted
fix: bignum parsed as Value
Fixes: #31 Signed-off-by: Ahmed Charles <[email protected]>
1 parent 303b478 commit 9299517

File tree

3 files changed

+306
-266
lines changed

3 files changed

+306
-266
lines changed

ciborium-ll/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,11 @@ mod tests {
460460
Header::Break,
461461
],
462462
),
463+
("c340", &[Header::Tag(3), Header::Bytes(Some(0))]),
464+
(
465+
"c35fff",
466+
&[Header::Tag(3), Header::Bytes(None), Header::Break],
467+
),
463468
];
464469

465470
for (bytes, headers) in data {

ciborium/src/de/mod.rs

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use alloc::{string::String, vec::Vec};
1010

1111
use ciborium_io::Read;
1212
use ciborium_ll::*;
13-
use serde::{de, de::Deserializer as _, forward_to_deserialize_any};
13+
use serde::{
14+
de::{self, value::BytesDeserializer, Deserializer as _},
15+
forward_to_deserialize_any,
16+
};
1417

1518
trait Expected<E: de::Error> {
1619
fn expected(self, kind: &'static str) -> E;
@@ -52,6 +55,8 @@ pub struct Deserializer<'b, R: Read> {
5255
recurse: usize,
5356
}
5457

58+
fn noop(_: u8) {}
59+
5560
impl<'a, R: Read> Deserializer<'a, R>
5661
where
5762
R::Error: core::fmt::Debug,
@@ -72,7 +77,12 @@ where
7277
}
7378

7479
#[inline]
75-
fn integer(&mut self, mut header: Option<Header>) -> Result<(bool, u128), Error<R::Error>> {
80+
fn integer<A: FnMut(u8)>(
81+
&mut self,
82+
mut header: Option<Header>,
83+
should_append: bool,
84+
mut append: A,
85+
) -> Result<(bool, u128), Error<R::Error>> {
7686
loop {
7787
let header = match header.take() {
7888
Some(h) => h,
@@ -99,7 +109,22 @@ where
99109
while let Some(chunk) = segment.pull(&mut buffer)? {
100110
for b in chunk {
101111
match index {
102-
16 => return Err(de::Error::custom("bigint too large")),
112+
16 => {
113+
if should_append {
114+
for v in value {
115+
append(v);
116+
}
117+
append(*b);
118+
index = 17; // Indicate overflow, see below
119+
continue;
120+
}
121+
return Err(de::Error::custom("bigint too large"));
122+
}
123+
17 => {
124+
debug_assert!(should_append);
125+
append(*b);
126+
continue;
127+
}
103128
0 if *b == 0 => continue, // Skip leading zeros
104129
_ => value[index] = *b,
105130
}
@@ -109,8 +134,12 @@ where
109134
}
110135
}
111136

112-
value[..index].reverse();
113-
Ok((neg, u128::from_le_bytes(value)))
137+
if index == 17 {
138+
Ok((false, 0))
139+
} else {
140+
value[..index].reverse();
141+
Ok((neg, u128::from_le_bytes(value)))
142+
}
114143
}
115144

116145
h => Err(h.expected("bytes")),
@@ -157,18 +186,21 @@ where
157186
let header = self.decoder.pull()?;
158187
self.decoder.push(header);
159188

160-
// If it is bytes, capture the length.
161-
let len = match header {
162-
Header::Bytes(x) => x,
163-
_ => None,
164-
};
165-
166-
match (tag, len) {
167-
(tag::BIGPOS, Some(len)) | (tag::BIGNEG, Some(len)) if len <= 16 => {
168-
let result = match self.integer(Some(Header::Tag(tag)))? {
169-
(false, raw) => return visitor.visit_u128(raw),
170-
(true, raw) => i128::try_from(raw).map(|x| x ^ !0),
171-
};
189+
match tag {
190+
tag::BIGPOS | tag::BIGNEG => {
191+
let mut bytes = Vec::new();
192+
let result =
193+
match self.integer(Some(Header::Tag(tag)), true, |b| bytes.push(b))? {
194+
(false, _) if !bytes.is_empty() => {
195+
let access = crate::tag::TagAccess::new(
196+
BytesDeserializer::new(&bytes),
197+
Some(tag),
198+
);
199+
return visitor.visit_enum(access);
200+
}
201+
(false, raw) => return visitor.visit_u128(raw),
202+
(true, raw) => i128::try_from(raw).map(|x| x ^ !0),
203+
};
172204

173205
match result {
174206
Ok(x) => visitor.visit_i128(x),
@@ -238,7 +270,7 @@ where
238270
}
239271

240272
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
241-
let result = match self.integer(None)? {
273+
let result = match self.integer(None, false, noop)? {
242274
(false, raw) => i64::try_from(raw),
243275
(true, raw) => i64::try_from(raw).map(|x| x ^ !0),
244276
};
@@ -250,7 +282,7 @@ where
250282
}
251283

252284
fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
253-
let result = match self.integer(None)? {
285+
let result = match self.integer(None, false, noop)? {
254286
(false, raw) => i128::try_from(raw),
255287
(true, raw) => i128::try_from(raw).map(|x| x ^ !0),
256288
};
@@ -274,7 +306,7 @@ where
274306
}
275307

276308
fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
277-
let result = match self.integer(None)? {
309+
let result = match self.integer(None, false, noop)? {
278310
(false, raw) => u64::try_from(raw),
279311
(true, ..) => return Err(de::Error::custom("unexpected negative integer")),
280312
};
@@ -286,7 +318,7 @@ where
286318
}
287319

288320
fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
289-
match self.integer(None)? {
321+
match self.integer(None, false, noop)? {
290322
(false, raw) => visitor.visit_u128(raw),
291323
(true, ..) => Err(de::Error::custom("unexpected negative integer")),
292324
}

0 commit comments

Comments
 (0)