asciiPercent computation: another potential multiplication overflow (#307)

* build: resolve a -Wconversion compiler warning

wordEncoder.cpp:312:91: warning: conversion from
‘std::__cxx11::basic_string<char>::size_type’ {aka ‘long unsigned
int’} to ‘double’ may change value [-Wconversion]
  312 | buffer.length() == 0 ? 1 : static_cast<double>(asciiCount) / buffer.length();
      |                                                              ~~~~~~~~~~~~~^~

* wordEncoder: replace value 100 for asciiPercent

asciiPercent is a ratio, and not counting in units of hundredths
anymore. The maximum value therefore should be 1 not 100.

* vmime: avoid integer multiply wraparound in text::createFromString

The change from commit v0.9.2-194-gb447adbe needs to be applied to
one more function that replicates the same code.

(If the input string is 42949673 characters long or larger, there will
be integer overflow on 32-bit platforms when multiplying by 100.
Switch that one computation to floating point.)
This commit is contained in:
Jan Engelhardt 2024-05-21 20:48:08 +02:00 committed by GitHub
parent d296c2d1d5
commit a2636bd4ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 5 additions and 7 deletions

View File

@ -269,7 +269,7 @@ shared_ptr <text> text::newFromString(const string& in, const charset& ch) {
void text::createFromString(const string& in, const charset& ch) {
size_t asciiPercent = 0;
double asciiPercent = 0;
removeAllWords();
@ -282,14 +282,12 @@ void text::createFromString(const string& in, const charset& ch) {
if (!alwaysEncode) {
const auto asciiCount = utility::stringUtils::countASCIIchars(in.begin(), in.end());
asciiPercent = (in.length() == 0 ? 100 : (100 * asciiCount) / in.length());
asciiPercent = in.length() == 0 ? 1 : static_cast<double>(asciiCount) / static_cast<double>(in.length());
}
// If there are "too much" non-ASCII chars, produce just one
// vmime::word. Because encoding happens word-wise, all of the input
// gets encoded.
// Cf. wordEncoder::guessBestEncoding for details
if (alwaysEncode || asciiPercent < 60) { // less than 60% ASCII chars
if (alwaysEncode || asciiPercent < 0.60) { // less than 60% ASCII chars
appendWord(make_shared <word>(in, ch));
return;

View File

@ -309,7 +309,7 @@ wordEncoder::Encoding wordEncoder::guessBestEncoding(
utility::stringUtils::countASCIIchars(buffer.begin(), buffer.end());
const double asciiPercent =
buffer.length() == 0 ? 100 : static_cast<double>(asciiCount) / buffer.length();
buffer.length() == 0 ? 1 : static_cast<double>(asciiCount) / static_cast<double>(buffer.length());
if (asciiPercent < 0.60) {
return ENCODING_B64;