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