Fix potential overflow problem with timevals #646

Closed
wants to merge 1 commit into
from

Projects

None yet

2 participants

@Andersbakken
Contributor

When comparing a null timeval with a current timeval using curlx_tvdiff on a 32-bit linux system there's an overflow happening.

Compiling with -fsanitize=undefined I get this warning on startup of our app using libcurl:

.../curl/lib/timeval.c:120:37: runtime error: signed integer overflow: 5873565 * 1000 cannot be represented in type 'long int'

The attached fix solves the problem by checking for a null timeval before comparing. Strictly speaking the function probably should return something that's guaranteed to be 64-bit but the majority of the usecases actually cast the result to an int and basically just compares two timevals that are close together so I decided against making a bigger change.

@Andersbakken Andersbakken Fix potential overflow problem when comparing a null timeval with an
current timeval.

Without this I get this warning from -fsanitize=undefined on startup of
our app:

.../curl/lib/timeval.c:120:37: runtime error: signed integer overflow: 5873565 * 1000 cannot be represented in type 'long int'
369a632
@bagder
Member
bagder commented Feb 11, 2016

Good catch! But since we use the *_tvdiff() function in quite a large number of places, maybe it would be better to fix that function to not do overflows? I'm thinking like this:

@@ -115,10 +115,17 @@ struct timeval curlx_tvnow(void)
  *
  * Returns: the time difference in number of milliseconds.
  */
 long curlx_tvdiff(struct timeval newer, struct timeval older)
 {
+#if SIZEOF_TIME_T < 8
+  /* for 32bit systems, add precaution to avoid overflow for really big time
+     differences */
+  time_t diff = newer.tv_sec-older.tv_sec;
+  if(diff > (0x7fffffff/1000))
+    return 0x7fffffff;
+#endif
   return (newer.tv_sec-older.tv_sec)*1000+
     (long)(newer.tv_usec-older.tv_usec)/1000;
 }

 /*
@bagder bagder self-assigned this Feb 11, 2016
@Andersbakken
Contributor

Yeah. That might be a better fix actually.

@bagder
Member
bagder commented Feb 12, 2016

I did some more math and I think the check needs to be

if(diff >= (0x7fffffff/1000))

... with a greater than or equal, as otherwise it can actually still go over the 31 bit limit. I'll merge this!

@bagder bagder added a commit that closed this pull request Feb 12, 2016
@bagder bagder curlx_tvdiff: handle 32bit time_t overflows
On 32bit systems, make sure we don't overflow and return funky values
for very large time differences.

Reported-by: Anders Bakken

Closes #646
d6b37d8
@bagder bagder closed this in d6b37d8 Feb 12, 2016
@Andersbakken
Contributor

Thanks.

Anders

On Thu, Feb 11, 2016 at 11:13 PM, Daniel Stenberg notifications@github.com
wrote:

Closed #646 #646 via d6b37d8
d6b37d8
.


Reply to this email directly or view it on GitHub
#646 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment