Skip to content

Commit 2677035

Browse files
author
Oliver Schneider
committed
json-encoder: panic when map key is not string or numeric
1 parent 62fb41c commit 2677035

File tree

1 file changed

+65
-48
lines changed

1 file changed

+65
-48
lines changed

src/libserialize/json.rs

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -420,16 +420,24 @@ fn fmt_number_or_null(v: f64) -> string::String {
420420
}
421421
}
422422

423+
#[deriving(PartialEq)]
424+
enum EmittingMapKeyState {
425+
NotEmitting,
426+
Emitting,
427+
EmittedValidMapKey,
428+
}
429+
423430
/// A structure for implementing serialization to JSON.
424431
pub struct Encoder<'a> {
425432
writer: &'a mut (io::Writer+'a),
433+
emitting_map_key: EmittingMapKeyState,
426434
}
427435

428436
impl<'a> Encoder<'a> {
429437
/// Creates a new JSON encoder whose output will be written to the writer
430438
/// specified.
431439
pub fn new(writer: &'a mut io::Writer) -> Encoder<'a> {
432-
Encoder { writer: writer }
440+
Encoder { writer: writer, emitting_map_key: EmittingMapKeyState::NotEmitting, }
433441
}
434442

435443
/// Encode the specified struct into a json [u8]
@@ -446,20 +454,31 @@ impl<'a> Encoder<'a> {
446454
}
447455
}
448456

457+
macro_rules! emit_enquoted_if_mapkey {
458+
($enc:ident,$e:expr) => {
459+
if $enc.emitting_map_key == EmittingMapKeyState::Emitting {
460+
$enc.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
461+
write!($enc.writer, "\"{}\"", $e)
462+
} else {
463+
write!($enc.writer, "{}", $e)
464+
}
465+
}
466+
}
467+
449468
impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
450469
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
451470

452-
fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
453-
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
454-
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
455-
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
456-
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
471+
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
472+
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
473+
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
474+
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
475+
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
457476

458-
fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
459-
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
460-
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
461-
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
462-
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
477+
fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
478+
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
479+
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
480+
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
481+
fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
463482

464483
fn emit_bool(&mut self, v: bool) -> EncodeResult {
465484
if v {
@@ -470,16 +489,18 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
470489
}
471490

472491
fn emit_f64(&mut self, v: f64) -> EncodeResult {
473-
write!(self.writer, "{}", fmt_number_or_null(v))
492+
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
474493
}
475494
fn emit_f32(&mut self, v: f32) -> EncodeResult {
476495
self.emit_f64(v as f64)
477496
}
478497

479498
fn emit_char(&mut self, v: char) -> EncodeResult {
499+
self.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
480500
escape_char(self.writer, v)
481501
}
482502
fn emit_str(&mut self, v: &str) -> EncodeResult {
503+
self.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
483504
escape_str(self.writer, v)
484505
}
485506

@@ -618,19 +639,13 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
618639
F: FnMut(&mut Encoder<'a>) -> EncodeResult,
619640
{
620641
if idx != 0 { try!(write!(self.writer, ",")) }
621-
// ref #12967, make sure to wrap a key in double quotes,
622-
// in the event that its of a type that omits them (eg numbers)
623-
let mut buf = Vec::new();
624-
// FIXME(14302) remove the transmute and unsafe block.
625-
unsafe {
626-
let mut check_encoder = Encoder::new(&mut buf);
627-
try!(f(transmute(&mut check_encoder)));
628-
}
629-
let out = str::from_utf8(buf[]).unwrap();
630-
let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
631-
if needs_wrapping { try!(write!(self.writer, "\"")); }
642+
self.emitting_map_key = EmittingMapKeyState::Emitting;
632643
try!(f(self));
633-
if needs_wrapping { try!(write!(self.writer, "\"")); }
644+
if self.emitting_map_key == EmittingMapKeyState::EmittedValidMapKey {
645+
self.emitting_map_key = EmittingMapKeyState::NotEmitting;
646+
} else {
647+
panic!("did not emit a valid map key, aborting encoding");
648+
}
634649
Ok(())
635650
}
636651

@@ -648,12 +663,18 @@ pub struct PrettyEncoder<'a> {
648663
writer: &'a mut (io::Writer+'a),
649664
curr_indent: uint,
650665
indent: uint,
666+
emitting_map_key: EmittingMapKeyState,
651667
}
652668

653669
impl<'a> PrettyEncoder<'a> {
654670
/// Creates a new encoder whose output will be written to the specified writer
655671
pub fn new(writer: &'a mut io::Writer) -> PrettyEncoder<'a> {
656-
PrettyEncoder { writer: writer, curr_indent: 0, indent: 2, }
672+
PrettyEncoder {
673+
writer: writer,
674+
curr_indent: 0,
675+
indent: 2,
676+
emitting_map_key: EmittingMapKeyState::NotEmitting,
677+
}
657678
}
658679

659680
/// Set the number of spaces to indent for each level.
@@ -669,17 +690,17 @@ impl<'a> PrettyEncoder<'a> {
669690
impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
670691
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
671692

672-
fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
673-
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
674-
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
675-
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
676-
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
693+
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
694+
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
695+
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
696+
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
697+
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
677698

678-
fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
679-
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
680-
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
681-
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
682-
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
699+
fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
700+
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
701+
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
702+
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
703+
fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
683704

684705
fn emit_bool(&mut self, v: bool) -> EncodeResult {
685706
if v {
@@ -690,16 +711,18 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
690711
}
691712

692713
fn emit_f64(&mut self, v: f64) -> EncodeResult {
693-
write!(self.writer, "{}", fmt_number_or_null(v))
714+
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
694715
}
695716
fn emit_f32(&mut self, v: f32) -> EncodeResult {
696717
self.emit_f64(v as f64)
697718
}
698719

699720
fn emit_char(&mut self, v: char) -> EncodeResult {
721+
self.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
700722
escape_char(self.writer, v)
701723
}
702724
fn emit_str(&mut self, v: &str) -> EncodeResult {
725+
self.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
703726
escape_str(self.writer, v)
704727
}
705728

@@ -887,19 +910,13 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
887910
try!(write!(self.writer, ",\n"));
888911
}
889912
try!(spaces(self.writer, self.curr_indent));
890-
// ref #12967, make sure to wrap a key in double quotes,
891-
// in the event that its of a type that omits them (eg numbers)
892-
let mut buf = Vec::new();
893-
// FIXME(14302) remove the transmute and unsafe block.
894-
unsafe {
895-
let mut check_encoder = PrettyEncoder::new(&mut buf);
896-
try!(f(transmute(&mut check_encoder)));
897-
}
898-
let out = str::from_utf8(buf[]).unwrap();
899-
let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
900-
if needs_wrapping { try!(write!(self.writer, "\"")); }
913+
self.emitting_map_key = EmittingMapKeyState::Emitting;
901914
try!(f(self));
902-
if needs_wrapping { try!(write!(self.writer, "\"")); }
915+
if self.emitting_map_key == EmittingMapKeyState::EmittedValidMapKey {
916+
self.emitting_map_key = EmittingMapKeyState::NotEmitting;
917+
} else {
918+
panic!("did not emit a valid map key, aborting encoding");
919+
}
903920
Ok(())
904921
}
905922

0 commit comments

Comments
 (0)