Skip to content

Commit

Permalink
fix: possible use-after-free bug in Array::new and Object::new
Browse files Browse the repository at this point in the history
  • Loading branch information
liuq19 committed Jun 4, 2024
1 parent c8d0fdd commit e8c4637
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
2 changes: 2 additions & 0 deletions scripts/sanitize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ sanitize() {
echo "Running tests with $SAN on $TARGET"
# # use single thread to make error info more readable and accurate
RUSTFLAGS="-Zsanitizer=$SAN" RUSTDOCFLAGS="-Zsanitizer=$SAN" cargo test --target $TARGET $3 -- --test-threads=1

RUSTFLAGS="-Zsanitizer=$SAN" RUSTDOCFLAGS="-Zsanitizer=$SAN" cargo test --doc --package sonic-rs --target $TARGET $3 -- --show-output --test-threads=1
}

sanitize_single() {
Expand Down
17 changes: 16 additions & 1 deletion src/value/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,24 @@ impl Array {
/// Constructs a new, empty `Array`.
///
/// The array will not allocate until elements are pushed onto it.
///
/// # Example
/// ```
/// use sonic_rs::{array, from_str, json, prelude::*, Array};
///
/// let mut arr: Array = from_str("[]").unwrap();
/// dbg!(&arr);
/// arr.push(array![]);
/// arr.push(1);
/// arr[0] = "hello".into();
/// arr[1] = array![].into();
/// assert_eq!(arr[0], "hello");
/// assert_eq!(arr[1], array![]);
/// ```
#[inline]
pub const fn new() -> Self {
let value = Value {
meta: super::node::Meta::new(super::node::ROOT_ARRAY, std::ptr::null()),
meta: super::node::Meta::new(super::node::ARRAY, std::ptr::null()),
data: super::node::Data {
achildren: std::ptr::null_mut(),
},
Expand Down Expand Up @@ -641,6 +655,7 @@ impl Array {
pub(crate) fn new_in(shared: Arc<Shared>) -> Self {
let mut array = Array::default();
array.0.mark_shared(shared.data_ptr());
array.0.mark_root();
std::mem::forget(shared);
array
}
Expand Down
3 changes: 2 additions & 1 deletion src/value/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl Debug for Value {

let ret = f
.debug_struct("Value")
.field("self ptr", &(self as *const _))
.field("data", &format!("{}", self))
.field("is_root", &self.is_root())
.field("shared_address", &self.meta.ptr())
Expand Down Expand Up @@ -1767,7 +1768,7 @@ impl Serialize for Value {
}
#[cfg(feature = "arbitrary_precision")]
RAWNUM | ROOT_RAWNUM => {
use ::serde::ser::SerializeStruct;
use serde::ser::SerializeStruct;

use crate::serde::rawnumber::TOKEN;
let mut struct_ = tri!(serializer.serialize_struct(TOKEN, 1));
Expand Down
25 changes: 23 additions & 2 deletions src/value/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,25 @@ impl Object {
}

/// Create a new empty object.
///
/// # Example
/// ```
/// use sonic_rs::{from_str, json, object, prelude::*, Object};
///
/// let mut obj: Object = from_str("{}").unwrap();
/// obj.insert(&"arr", object! {});
/// obj.insert(&"a", 1);
/// obj.insert(&"arr2", Object::new());
/// obj["a"] = json!(123);
/// obj["arr2"] = json!("hello world");
///
/// assert_eq!(obj["a"], 123);
/// assert_eq!(obj["arr2"], "hello world");
/// ```
#[inline]
pub const fn new() -> Object {
let value = Value {
meta: super::node::Meta::new(super::node::ROOT_OBJECT, std::ptr::null()),
meta: super::node::Meta::new(super::node::OBJECT, std::ptr::null()),
data: super::node::Data {
achildren: std::ptr::null_mut(),
},
Expand Down Expand Up @@ -578,14 +593,20 @@ impl<'a> VacantEntry<'a> {
/// # Examples
///
/// ```
/// use sonic_rs::{object, value::object::Entry};
/// use sonic_rs::{json, object, value::object::Entry};
///
/// let mut obj = object! {};
///
/// if let Entry::Vacant(entry) = obj.entry(&"hello") {
/// assert_eq!(entry.insert(1), &1);
/// }
///
/// if let Entry::Vacant(entry) = obj.entry(&"world") {
/// assert_eq!(entry.insert(json!("woo").clone()), "woo");
/// }
///
/// assert_eq!(obj.get(&"hello").unwrap(), 1);
/// assert_eq!(obj.get(&"world").unwrap(), "woo");
/// ```
pub fn insert<T: Into<Value>>(self, val: T) -> &'a mut Value {
let obj = unsafe { self.dormant_obj.awaken() };
Expand Down

0 comments on commit e8c4637

Please sign in to comment.