Skip to content

Commit ca30a50

Browse files
committed
Fix various issues in frequency trimming
Found by fuzzing. The frequency trimming functions did a bad job of checking for possible out of bounds accesses and didn't handle various failure cases correctly. Add suitable checks to fix the issues found. v2: fix one check, add several new ones
1 parent b9208c4 commit ca30a50

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

stcgal/protocols.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,15 +1089,19 @@ def handshake(self):
10891089
self.write_packet(packet)
10901090
self.pulse(timeout=1.0)
10911091
response = self.read_packet()
1092-
if response[0] != 0x65:
1092+
if len(response) < 36 or response[0] != 0x65:
10931093
raise StcProtocolException("incorrect magic in handshake packet")
10941094

10951095
# determine programming speed trim value
10961096
target_trim_a, target_count_a = struct.unpack(">HH", response[28:32])
10971097
target_trim_b, target_count_b = struct.unpack(">HH", response[32:36])
1098+
if target_count_a == target_count_b:
1099+
raise StcProtocolException("frequency trimming failed")
10981100
m = (target_trim_b - target_trim_a) / (target_count_b - target_count_a)
10991101
n = target_trim_a - m * target_count_a
11001102
program_trim = round(m * program_count + n)
1103+
if program_trim > 65535 or program_trim < 0:
1104+
raise StcProtocolException("frequency trimming failed")
11011105

11021106
# determine trim trials for second round
11031107
trim_a, count_a = struct.unpack(">HH", response[12:16])
@@ -1116,10 +1120,14 @@ def handshake(self):
11161120
target_count_a = count_a
11171121
target_count_b = count_b
11181122
# linear interpolate to find range to try next
1123+
if target_count_a == target_count_b:
1124+
raise StcProtocolException("frequency trimming failed")
11191125
m = (target_trim_b - target_trim_a) / (target_count_b - target_count_a)
11201126
n = target_trim_a - m * target_count_a
11211127
target_trim = round(m * user_count + n)
11221128
target_trim_start = min(max(target_trim - 5, target_trim_a), target_trim_b)
1129+
if target_trim_start + 11 > 65535 or target_trim_start < 0:
1130+
raise StcProtocolException("frequency trimming failed")
11231131

11241132
# trim challenge-response, second round
11251133
packet = bytes([0x65])
@@ -1131,7 +1139,7 @@ def handshake(self):
11311139
self.write_packet(packet)
11321140
self.pulse(timeout=1.0)
11331141
response = self.read_packet()
1134-
if response[0] != 0x65:
1142+
if len(response) < 56 or response[0] != 0x65:
11351143
raise StcProtocolException("incorrect magic in handshake packet")
11361144

11371145
# determine best trim value
@@ -1239,6 +1247,8 @@ def choose_range(self, packet, response, target_count):
12391247
calib_data = response[2:]
12401248
challenge_data = packet[2:]
12411249
calib_len = response[1]
1250+
if len(calib_data) < 2 * calib_len:
1251+
raise StcProtocolException("range calibration data missing")
12421252

12431253
for i in range(calib_len - 1):
12441254
count_a, count_b = struct.unpack(">HH", calib_data[2*i:2*i+4])
@@ -1248,6 +1258,8 @@ def choose_range(self, packet, response, target_count):
12481258
m = (trim_b - trim_a) / (count_b - count_a)
12491259
n = trim_a - m * count_a
12501260
target_trim = round(m * target_count + n)
1261+
if target_trim > 65536 or target_trim < 0:
1262+
raise StcProtocolException("frequency trimming failed")
12511263
return (target_trim, trim_range)
12521264

12531265
return None
@@ -1259,6 +1271,8 @@ def choose_trim(self, packet, response, target_count):
12591271
calib_data = response[2:]
12601272
challenge_data = packet[2:]
12611273
calib_len = response[1]
1274+
if len(calib_data) < 2 * calib_len:
1275+
raise StcProtocolException("trim calibration data missing")
12621276

12631277
best = None
12641278
best_count = sys.maxsize
@@ -1269,6 +1283,9 @@ def choose_trim(self, packet, response, target_count):
12691283
best_count = abs(count - target_count)
12701284
best = (trim_adj, trim_range), count
12711285

1286+
if not best:
1287+
raise StcProtocolException("frequency trimming failed")
1288+
12721289
return best
12731290

12741291
def calibrate(self):

0 commit comments

Comments
 (0)