Skip to content

Commit 4f50f38

Browse files
committed
fix(exif): Panic when parsing GPSInfo #37
1 parent 649a2f0 commit 4f50f38

File tree

4 files changed

+35
-31
lines changed

4 files changed

+35
-31
lines changed

src/exif.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,21 +254,27 @@ mod tests {
254254

255255
#[test_case("exif.heic", "+43.29013+084.22713+1595.950CRSWGS_84/")]
256256
#[test_case("exif.jpg", "+22.53113+114.02148/")]
257+
#[test_case("invalid-gps", "-")]
257258
fn gps(path: &str, gps_str: &str) {
258259
let f = open_sample(path).unwrap();
259260
let iter = parse_exif(f, None)
260261
.expect("should be Ok")
261262
.expect("should not be None");
262-
let gps_info = iter
263-
.parse_gps_info()
264-
.expect("should be parsed Ok")
265-
.expect("should not be None");
266263

267-
// let gps_info = iter
268-
// .consume_parse_gps_info()
269-
// .expect("should be parsed Ok")
270-
// .expect("should not be None");
271-
assert_eq!(gps_info.format_iso6709(), gps_str);
264+
if gps_str == "-" {
265+
assert!(iter.parse_gps_info().expect("should be ok").is_none());
266+
} else {
267+
let gps_info = iter
268+
.parse_gps_info()
269+
.expect("should be parsed Ok")
270+
.expect("should not be None");
271+
272+
// let gps_info = iter
273+
// .consume_parse_gps_info()
274+
// .expect("should be parsed Ok")
275+
// .expect("should not be None");
276+
assert_eq!(gps_info.format_iso6709(), gps_str);
277+
}
272278
}
273279

274280
#[cfg(feature = "async")]

src/exif/exif_iter.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -718,16 +718,16 @@ impl IfdIter {
718718
}
719719
ExifTag::GPSLatitude => {
720720
if let Some(v) = entry.as_urational_array() {
721-
gps.latitude = v.iter().collect();
721+
gps.latitude = v.try_into().ok()?;
722722
} else if let Some(v) = entry.as_irational_array() {
723-
gps.latitude = v.iter().collect();
723+
gps.latitude = v.try_into().ok()?;
724724
}
725725
}
726726
ExifTag::GPSLongitude => {
727727
if let Some(v) = entry.as_urational_array() {
728-
gps.longitude = v.iter().collect();
728+
gps.longitude = v.try_into().ok()?;
729729
} else if let Some(v) = entry.as_irational_array() {
730-
gps.longitude = v.iter().collect();
730+
gps.longitude = v.try_into().ok()?;
731731
}
732732
}
733733
ExifTag::GPSAltitude => {

src/exif/gps.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -131,28 +131,26 @@ impl FromIterator<URational> for LatLng {
131131
}
132132
}
133133

134-
impl<'a> FromIterator<&'a URational> for LatLng {
135-
fn from_iter<T: IntoIterator<Item = &'a URational>>(iter: T) -> Self {
136-
let mut values = iter.into_iter();
137-
Self(
138-
*values.next().unwrap(),
139-
*values.next().unwrap(),
140-
*values.next().unwrap(),
141-
)
134+
impl TryFrom<&Vec<URational>> for LatLng {
135+
type Error = crate::Error;
136+
fn try_from(value: &Vec<URational>) -> Result<Self, Self::Error> {
137+
if value.len() < 3 {
138+
Err(crate::Error::ParseFailed("invalid URational data".into()))
139+
} else {
140+
Ok(Self(value[0], value[1], value[2]))
141+
}
142142
}
143143
}
144-
145-
impl<'a> FromIterator<&'a IRational> for LatLng {
146-
fn from_iter<T: IntoIterator<Item = &'a IRational>>(iter: T) -> Self {
147-
let mut values = iter.into_iter();
148-
Self(
149-
(*values.next().unwrap()).into(),
150-
(*values.next().unwrap()).into(),
151-
(*values.next().unwrap()).into(),
152-
)
144+
impl TryFrom<&Vec<IRational>> for LatLng {
145+
type Error = crate::Error;
146+
fn try_from(value: &Vec<IRational>) -> Result<Self, Self::Error> {
147+
if value.len() < 3 {
148+
Err(crate::Error::ParseFailed("invalid URational data".into()))
149+
} else {
150+
Ok(Self(value[0].into(), value[1].into(), value[2].into()))
151+
}
153152
}
154153
}
155-
156154
pub struct InvalidISO6709Coord;
157155

158156
impl FromStr for GPSInfo {

testdata/invalid-gps

17.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)