Skip to content

Commit 3cbe4b8

Browse files
committed
rustc_metadata: sign-extend when decoding signed integers.
1 parent d47fd9e commit 3cbe4b8

File tree

1 file changed

+50
-17
lines changed

1 file changed

+50
-17
lines changed

src/librustc_metadata/rbml/reader.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -595,30 +595,27 @@ impl<'doc> Decoder<'doc> {
595595
}
596596

597597
// variable-length unsigned integer with different tags.
598-
// `first_tag` should be a tag for u8 or i8.
599-
// `last_tag` should be the largest allowed integer tag with the matching signedness.
598+
// `last_tag` should be the largest allowed unsigned integer tag.
600599
// all tags between them should be valid, in the order of u8, u16, u32 and u64.
601-
fn _next_int(&mut self,
602-
first_tag: EbmlEncoderTag,
600+
fn next_uint(&mut self,
603601
last_tag: EbmlEncoderTag)
604602
-> DecodeResult<u64> {
605603
if self.pos >= self.parent.end {
606604
return Err(Expected(format!("no more documents in current node!")));
607605
}
608606

609607
let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?;
610-
let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize {
611-
match r_tag - first_tag as usize {
608+
let r = if EsU8 as usize <= r_tag && r_tag <= last_tag as usize {
609+
match r_tag - EsU8 as usize {
612610
0 => doc_as_u8(r_doc) as u64,
613611
1 => doc_as_u16(r_doc) as u64,
614612
2 => doc_as_u32(r_doc) as u64,
615613
3 => doc_as_u64(r_doc),
616614
_ => unreachable!(),
617615
}
618616
} else {
619-
return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
617+
return Err(Expected(format!("expected EBML doc with tag EsU8 through {:?} but \
620618
found tag {:?}",
621-
first_tag,
622619
last_tag,
623620
r_tag)));
624621
};
@@ -629,7 +626,43 @@ impl<'doc> Decoder<'doc> {
629626
self.parent.end)));
630627
}
631628
self.pos = r_doc.end;
632-
debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
629+
debug!("next_uint({:?}) result={:?}", last_tag, r);
630+
Ok(r)
631+
}
632+
633+
// variable-length signed integer with different tags.
634+
// `last_tag` should be the largest allowed signed integer tag.
635+
// all tags between them should be valid, in the order of i8, i16, i32 and i64.
636+
fn next_int(&mut self,
637+
last_tag: EbmlEncoderTag)
638+
-> DecodeResult<i64> {
639+
if self.pos >= self.parent.end {
640+
return Err(Expected(format!("no more documents in current node!")));
641+
}
642+
643+
let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?;
644+
let r = if EsI8 as usize <= r_tag && r_tag <= last_tag as usize {
645+
match r_tag - EsI8 as usize {
646+
0 => doc_as_i8(r_doc) as i64,
647+
1 => doc_as_i16(r_doc) as i64,
648+
2 => doc_as_i32(r_doc) as i64,
649+
3 => doc_as_i64(r_doc),
650+
_ => unreachable!(),
651+
}
652+
} else {
653+
return Err(Expected(format!("expected EBML doc with tag EsI8 through {:?} but \
654+
found tag {:?}",
655+
last_tag,
656+
r_tag)));
657+
};
658+
if r_doc.end > self.parent.end {
659+
return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \
660+
{:#x}",
661+
r_doc.end,
662+
self.parent.end)));
663+
}
664+
self.pos = r_doc.end;
665+
debug!("next_int({:?}) result={:?}", last_tag, r);
633666
Ok(r)
634667
}
635668

@@ -662,19 +695,19 @@ impl<'doc> serialize::Decoder for Decoder<'doc> {
662695
}
663696

664697
fn read_u64(&mut self) -> DecodeResult<u64> {
665-
self._next_int(EsU8, EsU64)
698+
self.next_uint(EsU64)
666699
}
667700
fn read_u32(&mut self) -> DecodeResult<u32> {
668-
Ok(self._next_int(EsU8, EsU32)? as u32)
701+
Ok(self.next_uint(EsU32)? as u32)
669702
}
670703
fn read_u16(&mut self) -> DecodeResult<u16> {
671-
Ok(self._next_int(EsU8, EsU16)? as u16)
704+
Ok(self.next_uint(EsU16)? as u16)
672705
}
673706
fn read_u8(&mut self) -> DecodeResult<u8> {
674707
Ok(doc_as_u8(self.next_doc(EsU8)?))
675708
}
676709
fn read_usize(&mut self) -> DecodeResult<usize> {
677-
let v = self._next_int(EsU8, EsU64)?;
710+
let v = self.read_u64()?;
678711
if v > (::std::usize::MAX as u64) {
679712
Err(IntTooBig(v as usize))
680713
} else {
@@ -683,19 +716,19 @@ impl<'doc> serialize::Decoder for Decoder<'doc> {
683716
}
684717

685718
fn read_i64(&mut self) -> DecodeResult<i64> {
686-
Ok(self._next_int(EsI8, EsI64)? as i64)
719+
Ok(self.next_int(EsI64)? as i64)
687720
}
688721
fn read_i32(&mut self) -> DecodeResult<i32> {
689-
Ok(self._next_int(EsI8, EsI32)? as i32)
722+
Ok(self.next_int(EsI32)? as i32)
690723
}
691724
fn read_i16(&mut self) -> DecodeResult<i16> {
692-
Ok(self._next_int(EsI8, EsI16)? as i16)
725+
Ok(self.next_int(EsI16)? as i16)
693726
}
694727
fn read_i8(&mut self) -> DecodeResult<i8> {
695728
Ok(doc_as_u8(self.next_doc(EsI8)?) as i8)
696729
}
697730
fn read_isize(&mut self) -> DecodeResult<isize> {
698-
let v = self._next_int(EsI8, EsI64)? as i64;
731+
let v = self.next_int(EsI64)? as i64;
699732
if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
700733
debug!("FIXME \\#6122: Removing this makes this function miscompile");
701734
Err(IntTooBig(v as usize))

0 commit comments

Comments
 (0)