From 46d504b71d31fcc067ff8f7aa6b8a164a70ad197 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 25 Aug 2016 09:49:33 -0400 Subject: [PATCH 1/3] Don't allow underflow when calculating spans This subtraction can take place when doing things like creating a [field access expression through the AST builder][builder field access] (and in fact, as best I can tell, that's the only place it occurs) [builder field access]: https://github.com/rust-lang/rust/blob/a5e5ea1646367b82864af3a2a508993d76b792af/src/libsyntax/ext/build.rs#L636-L645 The assumption is that the given span starts and ends a the last byte of the field access. However, when doing macro expansion such as custom derive (or any other place the AST builder would manually be used), it's quite common to use the site of expansion as the span, as there's no other printable span to show. If that macro expansion is the first line of a file, the compiler will panic from underflow. Since byte positions are unsized, and performing this subtraction in a situation for underflow pretty much universally means you want to remain at 0, I've fixed this in the sub impl rather than the two problem cases of the AST builder. --- src/libsyntax_pos/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index b11bbea84abce..e463667a4f89b 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -549,7 +549,8 @@ impl Sub for BytePos { type Output = BytePos; fn sub(self, rhs: BytePos) -> BytePos { - BytePos((self.to_usize() - rhs.to_usize()) as u32) + let new_pos = self.to_usize().checked_sub(rhs.to_usize()).unwrap_or(0); + BytePos(new_post as u32) } } From 4fcd1b05b8e17a4d9157061f419a646b68f992f0 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 25 Aug 2016 11:34:15 -0400 Subject: [PATCH 2/3] Use saturating_sub --- src/libsyntax_pos/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index e463667a4f89b..a5bdbcf07d7e2 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -549,7 +549,7 @@ impl Sub for BytePos { type Output = BytePos; fn sub(self, rhs: BytePos) -> BytePos { - let new_pos = self.to_usize().checked_sub(rhs.to_usize()).unwrap_or(0); + let new_pos = self.to_usize().saturating_sub(rhs.to_usize()); BytePos(new_post as u32) } } From f97a3acc879bb5ddd0b0203db61c6a48b1f3e045 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 25 Aug 2016 12:03:24 -0400 Subject: [PATCH 3/3] Whoops! typo --- src/libsyntax_pos/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index a5bdbcf07d7e2..b57703e43ebb1 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -550,7 +550,7 @@ impl Sub for BytePos { fn sub(self, rhs: BytePos) -> BytePos { let new_pos = self.to_usize().saturating_sub(rhs.to_usize()); - BytePos(new_post as u32) + BytePos(new_pos as u32) } }