Skip to content

Commit 740da32

Browse files
committed
fix: bignum parsed as Value
Fixes: #31 Signed-off-by: Ahmed Charles <[email protected]>
1 parent ba48adc commit 740da32

File tree

3 files changed

+303
-266
lines changed

3 files changed

+303
-266
lines changed

ciborium-ll/src/lib.rs

+5
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

+50-21
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;
@@ -72,7 +75,11 @@ where
7275
}
7376

7477
#[inline]
75-
fn integer(&mut self, mut header: Option<Header>) -> Result<(bool, u128), Error<R::Error>> {
78+
fn integer<B: FnMut(u8)>(
79+
&mut self,
80+
mut header: Option<Header>,
81+
mut append: Option<B>,
82+
) -> Result<(bool, u128), Error<R::Error>> {
7683
loop {
7784
let header = match header.take() {
7885
Some(h) => h,
@@ -99,7 +106,22 @@ where
99106
while let Some(chunk) = segment.pull(&mut buffer)? {
100107
for b in chunk {
101108
match index {
102-
16 => return Err(de::Error::custom("bigint too large")),
109+
16 => {
110+
if let Some(app) = append.as_mut() {
111+
for v in value {
112+
app(v);
113+
}
114+
app(*b);
115+
index = 17; // Indicate overflow, see below
116+
continue;
117+
}
118+
return Err(de::Error::custom("bigint too large"));
119+
}
120+
17 => {
121+
// append is not None
122+
append.as_mut().unwrap()(*b);
123+
continue;
124+
}
103125
0 if *b == 0 => continue, // Skip leading zeros
104126
_ => value[index] = *b,
105127
}
@@ -109,8 +131,12 @@ where
109131
}
110132
}
111133

112-
value[..index].reverse();
113-
Ok((neg, u128::from_le_bytes(value)))
134+
if index == 17 {
135+
Ok((false, 0))
136+
} else {
137+
value[..index].reverse();
138+
Ok((neg, u128::from_le_bytes(value)))
139+
}
114140
}
115141

116142
h => Err(h.expected("bytes")),
@@ -157,18 +183,21 @@ where
157183
let header = self.decoder.pull()?;
158184
self.decoder.push(header);
159185

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-
};
186+
match tag {
187+
tag::BIGPOS | tag::BIGNEG => {
188+
let mut bytes = Vec::new();
189+
let result =
190+
match self.integer(Some(Header::Tag(tag)), Some(|b| bytes.push(b)))? {
191+
(false, _) if !bytes.is_empty() => {
192+
let access = crate::tag::TagAccess::new(
193+
BytesDeserializer::new(&bytes),
194+
Some(tag),
195+
);
196+
return visitor.visit_enum(access);
197+
}
198+
(false, raw) => return visitor.visit_u128(raw),
199+
(true, raw) => i128::try_from(raw).map(|x| x ^ !0),
200+
};
172201

173202
match result {
174203
Ok(x) => visitor.visit_i128(x),
@@ -238,7 +267,7 @@ where
238267
}
239268

240269
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
241-
let result = match self.integer(None)? {
270+
let result = match self.integer(None, None::<fn(_)>)? {
242271
(false, raw) => i64::try_from(raw),
243272
(true, raw) => i64::try_from(raw).map(|x| x ^ !0),
244273
};
@@ -250,7 +279,7 @@ where
250279
}
251280

252281
fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
253-
let result = match self.integer(None)? {
282+
let result = match self.integer(None, None::<fn(_)>)? {
254283
(false, raw) => i128::try_from(raw),
255284
(true, raw) => i128::try_from(raw).map(|x| x ^ !0),
256285
};
@@ -274,7 +303,7 @@ where
274303
}
275304

276305
fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
277-
let result = match self.integer(None)? {
306+
let result = match self.integer(None, None::<fn(_)>)? {
278307
(false, raw) => u64::try_from(raw),
279308
(true, ..) => return Err(de::Error::custom("unexpected negative integer")),
280309
};
@@ -286,7 +315,7 @@ where
286315
}
287316

288317
fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
289-
match self.integer(None)? {
318+
match self.integer(None, None::<fn(_)>)? {
290319
(false, raw) => visitor.visit_u128(raw),
291320
(true, ..) => Err(de::Error::custom("unexpected negative integer")),
292321
}

0 commit comments

Comments
 (0)