Skip to content

Commit 91c6da6

Browse files
authored
Merge pull request #174 from maciejhirsz/fixes
Fixes and formatting
2 parents 069bec7 + e5ba1fc commit 91c6da6

File tree

7 files changed

+92
-71
lines changed

7 files changed

+92
-71
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "json"
3-
version = "0.12.1"
3+
version = "0.12.2"
44
authors = ["Maciej Hirsz <[email protected]>"]
55
description = "JSON implementation in Rust"
66
repository = "https://github.com/maciejhirsz/json-rust"

src/codegen.rs

+22-27
Original file line numberDiff line numberDiff line change
@@ -390,32 +390,27 @@ fn extend_from_slice(dst: &mut Vec<u8>, src: &[u8]) {
390390
#[cfg(test)]
391391
mod tests {
392392
use super::*;
393-
use std::borrow::Borrow;
394-
use crate::JsonValue;
395-
use crate::parse;
396-
397-
// found while fuzzing the DumpGenerator
398-
399-
#[test]
400-
fn should_not_panic_on_bad_bytes() {
401-
let data = [0, 12, 128, 88, 64, 99].to_vec();
402-
let s = unsafe {
403-
String::from_utf8_unchecked(data)
404-
};
405-
406-
let mut generator = DumpGenerator::new();
407-
generator.write_string(&s);
408-
}
409-
410-
#[test]
411-
fn should_not_panic_on_bad_bytes_2() {
412-
let data = b"\x48\x48\x48\x57\x03\xE8\x48\x48\xE8\x03\x8F\x48\x29\x48\x48";
413-
let s = unsafe {
414-
String::from_utf8_unchecked(data.to_vec())
415-
};
416-
417-
let mut generator = DumpGenerator::new();
418-
generator.write_string(&s);
419-
}
420393

394+
// found while fuzzing the DumpGenerator
395+
#[test]
396+
fn should_not_panic_on_bad_bytes() {
397+
let data = [0, 12, 128, 88, 64, 99].to_vec();
398+
let s = unsafe {
399+
String::from_utf8_unchecked(data)
400+
};
401+
402+
let mut generator = DumpGenerator::new();
403+
generator.write_string(&s).unwrap();
404+
}
405+
406+
#[test]
407+
fn should_not_panic_on_bad_bytes_2() {
408+
let data = b"\x48\x48\x48\x57\x03\xE8\x48\x48\xE8\x03\x8F\x48\x29\x48\x48";
409+
let s = unsafe {
410+
String::from_utf8_unchecked(data.to_vec())
411+
};
412+
413+
let mut generator = DumpGenerator::new();
414+
generator.write_string(&s).unwrap();
415+
}
421416
}

src/number.rs

+52-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{ ops, fmt, f32, f64 };
2-
use std::num::FpCategory;
2+
use std::convert::{TryFrom, Infallible};
3+
use std::num::{FpCategory, TryFromIntError};
34
use crate::util::grisu2;
45
use crate::util::print_dec;
56

@@ -383,6 +384,23 @@ impl PartialEq<Number> for f32 {
383384
}
384385
}
385386

387+
/// Error type generated when trying to convert a `Number` into an
388+
/// integer of inadequate size.
389+
#[derive(Clone, Copy)]
390+
pub struct NumberOutOfScope;
391+
392+
impl From<Infallible> for NumberOutOfScope {
393+
fn from(_: Infallible) -> NumberOutOfScope {
394+
NumberOutOfScope
395+
}
396+
}
397+
398+
impl From<TryFromIntError> for NumberOutOfScope {
399+
fn from(_: TryFromIntError) -> NumberOutOfScope {
400+
NumberOutOfScope
401+
}
402+
}
403+
386404
macro_rules! impl_unsigned {
387405
($( $t:ty ),*) => ($(
388406
impl From<$t> for Number {
@@ -396,11 +414,24 @@ macro_rules! impl_unsigned {
396414
}
397415
}
398416

417+
impl TryFrom<Number> for $t {
418+
type Error = NumberOutOfScope;
419+
420+
fn try_from(num: Number) -> Result<Self, Self::Error> {
421+
let (positive, mantissa, exponent) = num.as_parts();
422+
423+
if !positive || exponent != 0 {
424+
return Err(NumberOutOfScope);
425+
}
426+
427+
TryFrom::try_from(mantissa).map_err(Into::into)
428+
}
429+
}
430+
399431
impl_integer!($t);
400432
)*)
401433
}
402434

403-
404435
macro_rules! impl_signed {
405436
($( $t:ty ),*) => ($(
406437
impl From<$t> for Number {
@@ -421,34 +452,32 @@ macro_rules! impl_signed {
421452
}
422453
}
423454

424-
impl_integer!($t);
425-
)*)
426-
}
427-
455+
impl TryFrom<Number> for $t {
456+
type Error = NumberOutOfScope;
428457

429-
macro_rules! impl_integer {
430-
($t:ty) => {
431-
impl From<Number> for $t {
432-
fn from(num: Number) -> $t {
458+
fn try_from(num: Number) -> Result<Self, Self::Error> {
433459
let (positive, mantissa, exponent) = num.as_parts();
434460

435-
if exponent <= 0 {
436-
if positive {
437-
mantissa as $t
438-
} else {
439-
-(mantissa as i64) as $t
440-
}
441-
} else {
442-
// This may overflow, which is fine
443-
if positive {
444-
(mantissa * 10u64.pow(exponent as u32)) as $t
445-
} else {
446-
(-(mantissa as i64) * 10i64.pow(exponent as u32)) as $t
447-
}
461+
if exponent != 0 {
462+
return Err(NumberOutOfScope);
448463
}
464+
465+
let mantissa = if positive {
466+
mantissa as i64
467+
} else {
468+
-(mantissa as i64)
469+
};
470+
471+
TryFrom::try_from(mantissa).map_err(Into::into)
449472
}
450473
}
451474

475+
impl_integer!($t);
476+
)*)
477+
}
478+
479+
macro_rules! impl_integer {
480+
($t:ty) => {
452481
impl PartialEq<$t> for Number {
453482
fn eq(&self, other: &$t) -> bool {
454483
*self == Number::from(*other)

src/parser.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ mod tests {
769769
use crate::stringify;
770770
use crate::JsonValue;
771771

772-
#[macro_use]
773772
use crate::object;
774773
use crate::array;
775774

@@ -840,7 +839,7 @@ mod tests {
840839
fn it_should_parse_json_nested_object() {
841840
let s = "{\"a\":1,\"b\":{\"c\":2,\"d\":{\"e\":{\"f\":{\"g\":3,\"h\":[]}}},\"i\":4,\"j\":[],\"k\":{\"l\":5,\"m\":{}}}}";
842841
let actual = parse(s).unwrap();
843-
let mut expected = object! {
842+
let expected = object! {
844843
"a" => 1,
845844
"b" => object!{
846845
"c" => 2,
@@ -868,7 +867,7 @@ mod tests {
868867
fn it_should_parse_json_complex_object() {
869868
let s = "{\"a\":1,\"b\":{\"c\":2,\"d\":{\"e\":{\"f\":{\"g\":3,\"h\":[{\"z\":1},{\"y\":2,\"x\":[{},{}]}]}}},\"i\":4,\"j\":[],\"k\":{\"l\":5,\"m\":{}}}}";
870869
let actual = parse(s).unwrap();
871-
let mut expected = object! {
870+
let expected = object! {
872871
"a" => 1,
873872
"b" => object!{
874873
"c" => 2,

src/util/print_dec.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
5959
return wr.write_all(b"0");
6060
}
6161

62-
let mut buf: [u8; 30] = mem::uninitialized();
63-
let mut curr = buf.len() as isize;
64-
let buf_ptr = buf.as_mut_ptr();
62+
const BUF_LEN: usize = 30;
63+
let mut buf = mem::MaybeUninit::<[u8; BUF_LEN]>::uninit();
64+
let mut curr = BUF_LEN as isize;
65+
let buf_ptr = buf.as_mut_ptr() as *mut u8;
6566
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
6667

6768
if exponent == 0 {
@@ -70,7 +71,7 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
7071
return wr.write_all(
7172
slice::from_raw_parts(
7273
buf_ptr.offset(curr),
73-
buf.len() - curr as usize
74+
BUF_LEN - curr as usize
7475
)
7576
);
7677
} else if exponent < 0 {
@@ -112,7 +113,7 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
112113
write_num(&mut n, &mut curr, buf_ptr, lut_ptr);
113114

114115
return wr.write_all(
115-
slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)
116+
slice::from_raw_parts(buf_ptr.offset(curr), BUF_LEN - curr as usize)
116117
);
117118
}
118119

@@ -159,7 +160,7 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
159160
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
160161
}
161162

162-
let printed_so_far = buf.len() as u16 - curr as u16;
163+
let printed_so_far = BUF_LEN as u16 - curr as u16;
163164

164165

165166
if printed_so_far <= e {
@@ -183,7 +184,7 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
183184
wr.write_all(
184185
slice::from_raw_parts(
185186
buf_ptr.offset(curr),
186-
buf.len() - curr as usize
187+
BUF_LEN - curr as usize
187188
)
188189
)?;
189190

@@ -203,14 +204,14 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
203204

204205
// Exponent greater than 0
205206
write_num(&mut n, &mut curr, buf_ptr, lut_ptr);
206-
let printed = buf.len() - curr as usize;
207+
let printed = BUF_LEN - curr as usize;
207208

208209
// No need for `e` notation, just print out zeroes
209210
if (printed + exponent as usize) <= 20 {
210211
wr.write_all(
211212
slice::from_raw_parts(
212213
buf_ptr.offset(curr),
213-
buf.len() - curr as usize
214+
BUF_LEN - curr as usize
214215
)
215216
)?;
216217

@@ -230,7 +231,7 @@ pub unsafe fn write<W: io::Write>(wr: &mut W, positive: bool, mut n: u64, expone
230231
wr.write_all(
231232
slice::from_raw_parts(
232233
buf_ptr.offset(curr),
233-
buf.len() - curr as usize
234+
BUF_LEN - curr as usize
234235
)
235236
)?;
236237
wr.write_all(b"e")?;

src/value/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::ops::{Index, IndexMut, Deref};
2+
use std::convert::TryInto;
23
use std::{fmt, mem, usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32};
34
use std::io::{self, Write};
45

@@ -229,11 +230,7 @@ impl JsonValue {
229230

230231
pub fn as_u64(&self) -> Option<u64> {
231232
self.as_number().and_then(|value| {
232-
if value.is_sign_positive() {
233-
Some(value.into())
234-
} else {
235-
None
236-
}
233+
value.try_into().ok()
237234
})
238235
}
239236

@@ -254,7 +251,7 @@ impl JsonValue {
254251
}
255252

256253
pub fn as_i64(&self) -> Option<i64> {
257-
self.as_number().map(|value| value.into())
254+
self.as_number().and_then(|value| value.try_into().ok())
258255
}
259256

260257
pub fn as_i32(&self) -> Option<i32> {

tests/customgen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
extern crate json;
33

44
use json::codegen::Generator;
5-
use json::object::{self, Object};
5+
use json::object::Object;
66
use json::{JsonValue, Null};
77
use std::io;
88

0 commit comments

Comments
 (0)