Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dag-cbor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ thiserror = "1.0.14"
[dev-dependencies]
libipld-macro = { path = "../macro" }
multihash = "0.10.1"
hex = "0.4.2"
11 changes: 10 additions & 1 deletion dag-cbor/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,17 @@ pub fn read_link<R: Read>(r: &mut R) -> Result<Cid> {
return Err(CborError::UnknownTag);
}
let len = read_u8(r)?;
if len == 0 {
return Err(CborError::LengthOutOfRange);
}
let bytes = read_bytes(r, len as usize)?;
Ok(Cid::try_from(bytes)?)
if bytes[0] != 0 {
return Err(CborError::InvalidCidPrefix(bytes[0]));
}

// skip the first byte per
// https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md#links
Ok(Cid::try_from(&bytes[1..])?)
}

pub trait ReadCbor: Sized {
Expand Down
5 changes: 4 additions & 1 deletion dag-cbor/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,11 @@ impl WriteCbor for Cid {
#[inline]
fn write_cbor<W: Write>(&self, w: &mut W) -> Result<()> {
write_tag(w, 42)?;
// insert zero byte per https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md#links
let bytes = self.to_bytes();
bytes.as_slice().write_cbor(w)?;
write_u64(w, 2, (bytes.len() + 1) as u64)?;
w.write_all(&[0])?;
w.write_all(&bytes)?;
Ok(())
}
}
Expand Down
5 changes: 4 additions & 1 deletion dag-cbor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub enum CborError {
/// Number larger than u64.
#[error("Number larger than u64.")]
NumberOutOfRange,
/// Length larger than usize.
/// Length larger than usize or too small, for example zero length cid field.
#[error("Length out of range.")]
LengthOutOfRange,
/// Unexpected cbor code.
Expand All @@ -60,6 +60,9 @@ pub enum CborError {
/// Utf8 error.
#[error("{0}")]
Utf8(#[from] std::str::Utf8Error),
/// The byte before Cid was not multibase identity prefix.
#[error("Invalid Cid prefix: {0}")]
InvalidCidPrefix(u8),
/// Cid error.
#[error("{0}")]
Cid(#[from] cid::Error),
Expand Down
47 changes: 47 additions & 0 deletions dag-cbor/tests/roundtrip.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use dag_cbor::{CborError, DagCborCodec};
use libipld_base::codec::Codec;

#[test]
fn roundtrip_with_cid() {
// generated with go-ipfs
// $ echo foobar > file1
// $ ipfs add foobar
// QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL
// $ echo -n '{ "foo": { "/": "QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL" } }' \
// | ipfs dag put
// bafyreibvjvcv745gig4mvqs4hctx4zfkono4rjejm2ta6gtyzkqxfjeily
// $ ipfs block get bafyreibvjvcv745gig4mvqs4hctx4zfkono4rjejm2ta6gtyzkqxfjeily \
// | xxd -ps | paste -s --delimiters=

let input =
"a163666f6fd82a582300122031c3d57080d8463a3c63b2923df5a1d40ad7a73eae5a14af584213e5f504ac33";
let input = hex::decode(input).unwrap();

let ipld = DagCborCodec::decode(&input).unwrap();
let bytes = DagCborCodec::encode(&ipld).unwrap().to_vec();

assert_eq!(input, bytes);
}

#[test]
fn invalid_cid_prefix() {
let input =
"a163666f6fd82a582301122031c3d57080d8463a3c63b2923df5a1d40ad7a73eae5a14af584213e5f504ac33";
let input = hex::decode(input).unwrap();

match DagCborCodec::decode(&input).unwrap_err() {
CborError::InvalidCidPrefix(1) => {}
x => panic!("unexpected error: {:?}", x),
}
}

#[test]
fn zero_length_cid() {
let input = "a163666f6fd82a5800";
let input = hex::decode(input).unwrap();

match DagCborCodec::decode(&input).unwrap_err() {
CborError::LengthOutOfRange => {}
x => panic!("unexpected error: {:?}", x),
}
}