Skip to content

Commit 2868a88

Browse files
authored
wasm-reduce: Fix integer overflows (#8665)
Use a larger size than int, and be careful when multiplying by 9.
1 parent 598b03e commit 2868a88

1 file changed

Lines changed: 18 additions & 18 deletions

File tree

src/tools/wasm-reduce/wasm-reduce.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ struct Reducer
351351
// @param factor how much to ignore. starting with a high factor skips through
352352
// most of the file, which is often faster than going one by one
353353
// from the start
354-
size_t reduceDestructively(int factor_) {
354+
size_t reduceDestructively(uint64_t factor_) {
355355
factor = factor_;
356356
// prepare
357357
loadWorking();
@@ -400,7 +400,7 @@ struct Reducer
400400
std::unique_ptr<Module> module;
401401
std::unique_ptr<Builder> builder;
402402
Index funcsSeen;
403-
int factor;
403+
uint64_t factor;
404404

405405
// write the module and see if the command still fails on it as expected
406406
bool writeAndTestReduction() {
@@ -822,7 +822,7 @@ struct Reducer
822822

823823
auto& data = segment->data;
824824
// when we succeed, try to shrink by more and more, similar to bisection
825-
size_t skip = 1;
825+
uint64_t skip = 1;
826826
for (size_t i = 0; i < data.size() && !data.empty(); i++) {
827827
if (justShrank || shouldTryToReduce(bonus)) {
828828
auto save = data;
@@ -838,7 +838,7 @@ struct Reducer
838838
std::cerr << "| shrank segment from " << save.size() << " => "
839839
<< data.size() << " (skip: " << skip << ")\n";
840840
noteReduction();
841-
skip = std::min(size_t(factor), 2 * skip);
841+
skip = std::min(factor, 2 * skip);
842842
} else {
843843
data = std::move(save);
844844
return false;
@@ -1003,8 +1003,8 @@ struct Reducer
10031003
if (numFuncs == 0) {
10041004
return false;
10051005
}
1006-
size_t skip = 1;
1007-
size_t maxSkip = 1;
1006+
uint64_t skip = 1;
1007+
uint64_t maxSkip = 1;
10081008
// If we just removed some functions in the previous iteration, keep trying
10091009
// to remove more as this is one of the most efficient ways to reduce.
10101010
bool justReduced = true;
@@ -1016,7 +1016,7 @@ struct Reducer
10161016
for (size_t x = 0; x < functionNames.size(); x++) {
10171017
size_t i = (base + x) % numFuncs;
10181018
if (!justReduced && functionsWeTriedToRemove.contains(functionNames[i]) &&
1019-
!shouldTryToReduce(std::max((factor / 5) + 1, 20000))) {
1019+
!shouldTryToReduce(std::max((factor / 5) + 1, uint64_t(20000)))) {
10201020
continue;
10211021
}
10221022
std::vector<Name> names;
@@ -1040,10 +1040,10 @@ struct Reducer
10401040
// Subtract 1 since the loop increments us anyhow by one: we want to
10411041
// skip over the skipped functions, and not any more.
10421042
x += skip - 1;
1043-
skip = std::min(size_t(factor), 2 * skip);
1043+
skip = std::min(factor, 2 * skip);
10441044
maxSkip = std::max(skip, maxSkip);
10451045
} else {
1046-
skip = std::max(skip / 2, size_t(1)); // or 1?
1046+
skip = std::max(skip / 2, uint64_t(1)); // or 1?
10471047
x += factor / 100;
10481048
}
10491049
}
@@ -1078,9 +1078,9 @@ struct Reducer
10781078
for (auto& exp : module->exports) {
10791079
exports.push_back(*exp);
10801080
}
1081-
size_t skip = 1;
1081+
uint64_t skip = 1;
10821082
for (size_t i = 0; i < exports.size(); i++) {
1083-
if (!shouldTryToReduce(std::max((factor / 100) + 1, 1000))) {
1083+
if (!shouldTryToReduce(std::max((factor / 100) + 1, uint64_t(1000)))) {
10841084
continue;
10851085
}
10861086
std::vector<Export> currExports;
@@ -1097,12 +1097,12 @@ struct Reducer
10971097
for (auto exp : currExports) {
10981098
module->addExport(new Export(exp));
10991099
}
1100-
skip = std::max(skip / 2, size_t(1)); // or 1?
1100+
skip = std::max(skip / 2, uint64_t(1)); // or 1?
11011101
} else {
11021102
std::cerr << "| removed " << currExports.size() << " exports\n";
11031103
noteReduction(currExports.size());
11041104
i += skip;
1105-
skip = std::min(size_t(factor), 2 * skip);
1105+
skip = std::min(factor, 2 * skip);
11061106
}
11071107
}
11081108
// If we are left with a single function that is not exported or used in
@@ -1560,7 +1560,7 @@ More documentation can be found at
15601560

15611561
std::cerr << "|starting reduction!\n";
15621562

1563-
int factor = binary ? workingSize * 2 : workingSize / 10;
1563+
uint64_t factor = binary ? uint64_t(workingSize) * 2 : workingSize / 10;
15641564

15651565
size_t lastDestructiveReductions = 0;
15661566
size_t lastPostPassesSize = 0;
@@ -1623,7 +1623,7 @@ More documentation can be found at
16231623
// we get "stuck" cycling through them. In that case we simply need to do
16241624
// more destructive reductions to make real progress. For that reason,
16251625
// decrease the factor by some small percentage.
1626-
factor = std::max(1, (factor * 9) / 10);
1626+
factor = std::max(uint64_t(1), uint64_t(factor * 0.9));
16271627
} else {
16281628
if (factor > 10) {
16291629
factor = (factor / 3) + 1;
@@ -1634,7 +1634,7 @@ More documentation can be found at
16341634

16351635
// no point in a factor larger than the size
16361636
assert(newSize > 4); // wasm modules are >4 bytes anyhow
1637-
factor = std::min(factor, int(newSize) / 4);
1637+
factor = std::min(factor, uint64_t(newSize / 4));
16381638

16391639
// try to reduce destructively. if a high factor fails to find anything,
16401640
// quickly try a lower one (no point in doing passes until we reduce
@@ -1650,8 +1650,8 @@ More documentation can be found at
16501650
stopping = true;
16511651
break;
16521652
}
1653-
factor = std::max(
1654-
1, factor / 4); // quickly now, try to find *something* we can reduce
1653+
// Quickly try to find *something* we can reduce.
1654+
factor = std::max(uint64_t(1), factor / 4);
16551655
}
16561656

16571657
std::cerr << "| destructive reduction led to size: " << file_size(working)

0 commit comments

Comments
 (0)