Skip to content

Commit

Permalink
Merge pull request #54 from Kijewski/pr-macos-use-after-free
Browse files Browse the repository at this point in the history
Fix potential use after free in MacOS / iOS impl
  • Loading branch information
Kijewski committed Aug 16, 2022
2 parents 7a3b109 + 4331500 commit 46ac343
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "iana-time-zone"
description = "get the IANA time zone for the current system"
version = "0.1.44"
version = "0.1.45"
authors = ["Andrew Straw <strawman@astraw.com>"]
repository = "https://github.com/strawlab/iana-time-zone"
license = "MIT OR Apache-2.0"
Expand Down
71 changes: 55 additions & 16 deletions src/tz_macos.rs
@@ -1,22 +1,61 @@
use core_foundation_sys::base::{CFRelease, CFTypeRef};
use core_foundation_sys::string::{kCFStringEncodingUTF8, CFStringGetCStringPtr};
use core_foundation_sys::base::{Boolean, CFRange, CFRelease, CFTypeRef};
use core_foundation_sys::string::{
kCFStringEncodingUTF8, CFStringGetBytes, CFStringGetCStringPtr, CFStringGetLength,
};
use core_foundation_sys::timezone::{CFTimeZoneCopySystem, CFTimeZoneGetName};

pub(crate) fn get_timezone_inner() -> Result<String, crate::GetTimezoneError> {
unsafe {
Dropping::new(CFTimeZoneCopySystem())
.and_then(|tz| Dropping::new(CFTimeZoneGetName(tz.0)))
.and_then(|name| {
let name = CFStringGetCStringPtr(name.0, kCFStringEncodingUTF8);
if name.is_null() {
None
} else {
Some(name)
}
})
.and_then(|name| std::ffi::CStr::from_ptr(name).to_str().ok())
.map(|name| name.to_owned())
.ok_or(crate::GetTimezoneError::OsError)
unsafe { get_timezone().ok_or(crate::GetTimezoneError::OsError) }
}

#[inline]
unsafe fn get_timezone() -> Option<String> {
// The longest name in the IANA time zone database is 25 ASCII characters long.
const MAX_LEN: usize = 32;

// Get system time zone, and borrow its name.
let tz = Dropping::new(CFTimeZoneCopySystem())?;
let name = CFTimeZoneGetName(tz.0);
if name.is_null() {
return None;
}

// If the name is encoded in UTF-8, copy it directly.
let cstr = CFStringGetCStringPtr(name, kCFStringEncodingUTF8);
if !cstr.is_null() {
let cstr = std::ffi::CStr::from_ptr(cstr);
if let Ok(name) = cstr.to_str() {
return Some(name.to_owned());
}
}

// Otherwise convert the name to UTF-8.
let mut buf = [0; MAX_LEN];
let mut buf_bytes = 0;
let range = CFRange {
location: 0,
length: CFStringGetLength(name),
};
if CFStringGetBytes(
name,
range,
kCFStringEncodingUTF8,
b'\0',
false as Boolean,
buf.as_mut_ptr(),
buf.len() as isize,
&mut buf_bytes,
) != range.length
{
// Could not convert the name.
None
} else if !(1..MAX_LEN as isize).contains(&buf_bytes) {
// The name should not be empty, or excessively long.
None
} else {
// Convert the name to a `String`.
let name = core::str::from_utf8(&buf[..buf_bytes as usize]).ok()?;
Some(name.to_owned())
}
}

Expand Down

0 comments on commit 46ac343

Please sign in to comment.