Fix printf issue found in GDB

This commit is contained in:
jD91mZM2
2020-08-05 16:48:03 +02:00
parent 4f93e43593
commit 72532b8280
3 changed files with 22 additions and 11 deletions
+17 -11
View File
@@ -18,7 +18,7 @@ use crate::{
// |____/ \___/|_|_|\___|_| | .__/|_|\__,_|\__\___(_)
// |_|
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum IntKind {
Byte,
Short,
@@ -29,7 +29,7 @@ enum IntKind {
PtrDiff,
Size,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum FmtKind {
Percent,
@@ -52,8 +52,8 @@ enum Number {
Next,
}
impl Number {
unsafe fn resolve(&self, varargs: &mut VaListCache, ap: &mut VaList) -> usize {
let arg = match *self {
unsafe fn resolve(self, varargs: &mut VaListCache, ap: &mut VaList) -> usize {
let arg = match self {
Number::Static(num) => return num,
Number::Index(i) => varargs.get(i - 1, ap, None),
Number::Next => {
@@ -231,12 +231,16 @@ impl VaListCache {
default: Option<(FmtKind, IntKind)>,
) -> VaArg {
if let Some(&arg) = self.args.get(i) {
// This value is already cached
let mut arg = arg;
if let Some((fmtkind, intkind)) = default {
// ...but as a different type
arg = arg.transmute(fmtkind, intkind);
}
return arg;
}
// Get all values before this value
while self.args.len() < i {
// We can't POSSIBLY know the type if we reach this
// point. Reaching here means there are unused gaps in the
@@ -244,10 +248,14 @@ impl VaListCache {
// defaulting to c_int.
self.args.push(VaArg::c_int(ap.arg::<c_int>()))
}
// Add the value to the cache
self.args.push(match default {
Some((fmtkind, intkind)) => VaArg::arg_from(fmtkind, intkind, ap),
None => VaArg::c_int(ap.arg::<c_int>()),
});
// Return the value
self.args[i]
}
}
@@ -462,7 +470,7 @@ fn fmt_float_nonfinite<W: Write>(w: &mut W, float: c_double, case: FmtCase) -> i
struct PrintfIter {
format: *const u8,
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
struct PrintfArg {
index: Option<usize>,
alternate: bool,
@@ -472,11 +480,11 @@ struct PrintfArg {
sign_always: bool,
min_width: Number,
precision: Option<Number>,
pad_zero: Number,
intkind: IntKind,
fmt: u8,
fmtkind: FmtKind,
}
#[derive(Debug)]
enum PrintfFmt {
Plain(&'static [u8]),
Arg(PrintfArg),
@@ -540,9 +548,6 @@ impl Iterator for PrintfIter {
None
};
let pad_space = if zero { Number::Static(0) } else { min_width };
let pad_zero = if zero { min_width } else { Number::Static(0) };
// Integer size:
let mut intkind = IntKind::Int;
loop {
@@ -595,7 +600,6 @@ impl Iterator for PrintfIter {
sign_always,
min_width,
precision,
pad_zero,
intkind,
fmt,
fmtkind,
@@ -643,6 +647,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) ->
.push(VaArg::arg_from(arg.fmtkind, arg.intkind, &mut ap)),
}
}
// Make sure, in order, the positional arguments exist with the specified type
for (i, arg) in positional {
varargs.get(i, &mut ap, Some(arg));
@@ -665,7 +670,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) ->
let sign_always = arg.sign_always;
let min_width = arg.min_width.resolve(&mut varargs, &mut ap);
let precision = arg.precision.map(|n| n.resolve(&mut varargs, &mut ap));
let pad_zero = arg.pad_zero.resolve(&mut varargs, &mut ap);
let pad_zero = if zero { min_width } else { 0 };
let signed_space = match pad_zero {
0 => min_width as isize,
_ => 0,
@@ -685,6 +690,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) ->
_ => None,
};
let index = arg.index.map(|i| i - 1).unwrap_or_else(|| {
if fmtkind == FmtKind::Percent {
0
+2
View File
@@ -60,6 +60,8 @@ Non-finite float madness:
%F: INF -INF NAN -NAN
%g: inf -inf nan -nan
%G: INF -INF NAN -NAN
Things that have been buggy
+05
Testing asprintf...
printed: test string, value: 11
printed: test string 2, value: 13
+3
View File
@@ -75,6 +75,9 @@ int main(void) {
printf("\n");
}
puts("Things that have been buggy");
printf("%s%0*lu\n", "+", 2, 5l); // this format string was found in GDB
puts("Testing asprintf...");
char *s = NULL;
int res = asprintf(&s, "test string");