Skip to content

Commit 59fa193

Browse files
authored
Create a size-limited fmt::Formatter outside of v0 for full limiting. (#50)
* Create a size-limited `fmt::Formatter` outside of v0 for full limiting. * v0: ban `write!` and use `fmt::Display::fmt(x, f)` instead of `x.fmt(f)`.
1 parent b1bbc0d commit 59fa193

File tree

2 files changed

+67
-53
lines changed

2 files changed

+67
-53
lines changed

src/lib.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extern crate std;
3333
mod legacy;
3434
mod v0;
3535

36-
use core::fmt;
36+
use core::fmt::{self, Write as _};
3737

3838
/// Representation of a demangled symbol name.
3939
pub struct Demangle<'a> {
@@ -176,12 +176,51 @@ fn is_ascii_punctuation(c: char) -> bool {
176176
}
177177
}
178178

179+
impl<'a> fmt::Display for DemangleStyle<'a> {
180+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181+
match *self {
182+
DemangleStyle::Legacy(ref d) => fmt::Display::fmt(d, f),
183+
DemangleStyle::V0(ref d) => fmt::Display::fmt(d, f),
184+
}
185+
}
186+
}
187+
188+
// Maximum size of the symbol that we'll print.
189+
const MAX_SIZE: usize = 1_000_000;
190+
191+
struct LimitedFmtWriter<F> {
192+
remaining: usize,
193+
inner: F,
194+
}
195+
196+
impl<F: fmt::Write> fmt::Write for LimitedFmtWriter<F> {
197+
fn write_str(&mut self, s: &str) -> fmt::Result {
198+
let remaining = self.remaining.checked_sub(s.len());
199+
self.remaining = remaining.unwrap_or(0);
200+
201+
match remaining {
202+
Some(_) => self.inner.write_str(s),
203+
None => Err(fmt::Error),
204+
}
205+
}
206+
}
207+
179208
impl<'a> fmt::Display for Demangle<'a> {
180209
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210+
let alternate = f.alternate();
211+
let mut f = LimitedFmtWriter {
212+
remaining: MAX_SIZE,
213+
inner: f,
214+
};
181215
match self.style {
182216
None => f.write_str(self.original)?,
183-
Some(DemangleStyle::Legacy(ref d)) => fmt::Display::fmt(d, f)?,
184-
Some(DemangleStyle::V0(ref d)) => fmt::Display::fmt(d, f)?,
217+
Some(ref d) => {
218+
if alternate {
219+
write!(f, "{:#}", d)?;
220+
} else {
221+
write!(f, "{}", d)?;
222+
}
223+
}
185224
}
186225
f.write_str(self.suffix)
187226
}

src/v0.rs

+25-50
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
use core::char;
22
use core::fmt;
3-
use core::fmt::{Display, Write};
3+
4+
#[allow(unused_macros)]
5+
macro_rules! write {
6+
($($ignored:tt)*) => {
7+
compile_error!("use `fmt::Trait::fmt(&value, self.out)` instead of write!")
8+
};
9+
}
410

511
// Maximum recursion depth when parsing symbols before we just bail out saying
612
// "this symbol is invalid"
713
const MAX_DEPTH: u32 = 500;
814

9-
// Approximately the maximum size of the symbol that we'll print. This is
10-
// approximate because it only limits calls writing to `LimitedFormatter`, but
11-
// not all writes exclusively go through `LimitedFormatter`. Some writes go
12-
// directly to the underlying formatter, but when that happens we always write
13-
// at least a little to the `LimitedFormatter`.
14-
const MAX_APPROX_SIZE: usize = 1_000_000;
15-
1615
/// Representation of a demangled symbol name.
1716
pub struct Demangle<'a> {
1817
inner: &'a str,
@@ -68,19 +67,15 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
6867
Ok((Demangle { inner }, &parser.sym[parser.next..]))
6968
}
7069

71-
impl<'s> Display for Demangle<'s> {
70+
impl<'s> fmt::Display for Demangle<'s> {
7271
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73-
let mut remaining = MAX_APPROX_SIZE;
7472
let mut printer = Printer {
7573
parser: Ok(Parser {
7674
sym: self.inner,
7775
next: 0,
7876
depth: 0,
7977
}),
80-
out: LimitedFormatter {
81-
remaining: &mut remaining,
82-
inner: f,
83-
},
78+
out: f,
8479
bound_lifetime_depth: 0,
8580
};
8681
printer.print_path(true)
@@ -222,7 +217,7 @@ impl<'s> Ident<'s> {
222217
}
223218
}
224219

225-
impl<'s> Display for Ident<'s> {
220+
impl<'s> fmt::Display for Ident<'s> {
226221
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227222
self.try_small_punycode_decode(|chars| {
228223
for &c in chars {
@@ -605,7 +600,7 @@ impl<'s> Parser<'s> {
605600

606601
struct Printer<'a, 'b: 'a, 's> {
607602
parser: Result<Parser<'s>, Invalid>,
608-
out: LimitedFormatter<'a, 'b>,
603+
out: &'a mut fmt::Formatter<'b>,
609604
bound_lifetime_depth: u32,
610605
}
611606

@@ -649,10 +644,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
649644
fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> {
650645
Printer {
651646
parser: self.parser_mut().and_then(|p| p.backref()),
652-
out: LimitedFormatter {
653-
remaining: self.out.remaining,
654-
inner: self.out.inner,
655-
},
647+
out: self.out,
656648
bound_lifetime_depth: self.bound_lifetime_depth,
657649
}
658650
}
@@ -686,11 +678,11 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
686678
// Try to print lifetimes alphabetically first.
687679
if depth < 26 {
688680
let c = (b'a' + depth as u8) as char;
689-
c.fmt(self.out.inner)
681+
fmt::Display::fmt(&c, self.out)
690682
} else {
691683
// Use `'_123` after running out of letters.
692684
self.out.write_str("_")?;
693-
depth.fmt(self.out.inner)
685+
fmt::Display::fmt(&depth, self.out)
694686
}
695687
}
696688
None => invalid!(self),
@@ -750,10 +742,10 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
750742
let dis = parse!(self, disambiguator);
751743
let name = parse!(self, ident);
752744

753-
name.fmt(self.out.inner)?;
754-
if !self.out.inner.alternate() {
745+
fmt::Display::fmt(&name, self.out)?;
746+
if !self.out.alternate() {
755747
self.out.write_str("[")?;
756-
fmt::LowerHex::fmt(&dis, self.out.inner)?;
748+
fmt::LowerHex::fmt(&dis, self.out)?;
757749
self.out.write_str("]")?;
758750
}
759751
}
@@ -772,22 +764,22 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
772764
match ns {
773765
'C' => self.out.write_str("closure")?,
774766
'S' => self.out.write_str("shim")?,
775-
_ => ns.fmt(self.out.inner)?,
767+
_ => fmt::Display::fmt(&ns, self.out)?,
776768
}
777769
if !name.ascii.is_empty() || !name.punycode.is_empty() {
778770
self.out.write_str(":")?;
779-
name.fmt(self.out.inner)?;
771+
fmt::Display::fmt(&name, self.out)?;
780772
}
781773
self.out.write_str("#")?;
782-
dis.fmt(self.out.inner)?;
774+
fmt::Display::fmt(&dis, self.out)?;
783775
self.out.write_str("}")?;
784776
}
785777

786778
// Implementation-specific/unspecified namespaces.
787779
None => {
788780
if !name.ascii.is_empty() || !name.punycode.is_empty() {
789781
self.out.write_str("::")?;
790-
name.fmt(self.out.inner)?;
782+
fmt::Display::fmt(&name, self.out)?;
791783
}
792784
}
793785
}
@@ -1000,7 +992,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1000992
}
1001993

1002994
let name = parse!(self, ident);
1003-
name.fmt(self.out.inner)?;
995+
fmt::Display::fmt(&name, self.out)?;
1004996
self.out.write_str(" = ")?;
1005997
self.print_type()?;
1006998
}
@@ -1039,7 +1031,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10391031
_ => invalid!(self),
10401032
};
10411033

1042-
if !self.out.inner.alternate() {
1034+
if !self.out.alternate() {
10431035
self.out.write_str(": ")?;
10441036
let ty = basic_type(ty_tag).unwrap();
10451037
self.out.write_str(ty)?;
@@ -1061,7 +1053,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10611053
for c in hex.chars() {
10621054
v = (v << 4) | (c.to_digit(16).unwrap() as u64);
10631055
}
1064-
v.fmt(self.out.inner)
1056+
fmt::Display::fmt(&v, self.out)
10651057
}
10661058

10671059
fn print_const_int(&mut self) -> fmt::Result {
@@ -1093,7 +1085,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10931085
v = (v << 4) | (c.to_digit(16).unwrap() as u32);
10941086
}
10951087
if let Some(c) = char::from_u32(v) {
1096-
write!(self.out, "{:?}", c)
1088+
fmt::Debug::fmt(&c, self.out)
10971089
} else {
10981090
invalid!(self)
10991091
}
@@ -1792,20 +1784,3 @@ RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRB_E"
17921784
);
17931785
}
17941786
}
1795-
1796-
struct LimitedFormatter<'a, 'b> {
1797-
remaining: &'a mut usize,
1798-
inner: &'a mut fmt::Formatter<'b>,
1799-
}
1800-
1801-
impl Write for LimitedFormatter<'_, '_> {
1802-
fn write_str(&mut self, s: &str) -> fmt::Result {
1803-
match self.remaining.checked_sub(s.len()) {
1804-
Some(amt) => {
1805-
*self.remaining = amt;
1806-
self.inner.write_str(s)
1807-
}
1808-
None => Err(fmt::Error),
1809-
}
1810-
}
1811-
}

0 commit comments

Comments
 (0)