Blob Blame History Raw
From 2934cc1537e1b3da17340ca87b868ea1a7063eaf Mon Sep 17 00:00:00 2001
From: Mamoru TASAKA <mtasaka@fedoraproject.org>
Date: Mon, 15 Sep 2014 02:21:59 +0900
Subject: [PATCH 1002/1005] analogtv_setup_frame: clip too large double value
 for hni

gcc49 detected the following error:

../../hacks/analogtv.c:957:11: runtime error: signed integer overflow: 2147463385 + 29231 cannot be represented in type 'int [262]'
../../hacks/analogtv.c:957:41: runtime error: signed integer overflow: -2147452808 + -32768 cannot be represented in type 'int [262]'

Well, the part "[262]" in this message seems strange, however anyway
in analogtv_setup_frame(), when it->hashnoise_rpm is positive and too small,
the internal of the parenthesis for calculating hni
(i.e. ANALOGTV_V * ANALOGTV_H * 256.0 / (it->hashnoise_rpm * 16.0 / 60.0 / 60.0))
can get very large number, and casting such large double value to int
produces undefined behavior (undefined behavior once). On my machine
it seems that this gets near INT_MIN. Then hni + (int)(random()%65536)-32768
can again produces undefined behavior (by signed integer overflow).

So let's clip too large double value for hni and avoid overflow.
---
 hacks/analogtv.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hacks/analogtv.c b/hacks/analogtv.c
index 009d7bc..20acc0d 100644
--- a/hacks/analogtv.c
+++ b/hacks/analogtv.c
@@ -942,11 +942,13 @@ analogtv_setup_frame(analogtv *it)
   }
   if (it->hashnoise_rpm > 0.0) {
     int hni;
+    double hni_double;
     int hnc=it->hashnoise_counter; /* in 24.8 format */
 
     /* Convert rpm of a 16-pole motor into dots in 24.8 format */
-    hni = (int)(ANALOGTV_V * ANALOGTV_H * 256.0 /
-                (it->hashnoise_rpm * 16.0 / 60.0 / 60.0));
+    hni_double = ANALOGTV_V * ANALOGTV_H * 256.0 /
+                (it->hashnoise_rpm * 16.0 / 60.0 / 60.0);
+    hni = (hni_double <= INT_MAX) ? (int)hni_double : INT_MAX;
 
     while (hnc < (ANALOGTV_V * ANALOGTV_H)<<8) {
       y=(hnc>>8)/ANALOGTV_H;
@@ -955,7 +957,12 @@ analogtv_setup_frame(analogtv *it)
       if (x>0 && x<ANALOGTV_H - ANALOGTV_HASHNOISE_LEN) {
         it->hashnoise_times[y]=x;
       }
-      hnc += hni + (int)(random()%65536)-32768;
+      /* hnc += hni + (int)(random()%65536)-32768; */
+      {
+        hnc += (int)(random()%65536)-32768;
+        if ((hnc >= 0) && (INT_MAX - hnc < hni)) break;
+        hnc += hni;
+      }
     }
 /*    hnc -= (ANALOGTV_V * ANALOGTV_H)<<8;*/
   }
-- 
2.1.0