Convert various callers of strtou?ll() to call strntou?ll()

Where size is known or can readily be determined.

Change-Id: I442e7ebb3757fdbf7d021a15e19aeba533b590a5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2021-08-27 15:25:26 +02:00
parent 5644af6f8a
commit 7d33779a79
8 changed files with 32 additions and 29 deletions

View File

@ -3529,6 +3529,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
(std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit; (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit;
const auto locker = qt_scoped_lock(environmentMutex); const auto locker = qt_scoped_lock(environmentMutex);
size_t size;
#ifdef Q_CC_MSVC #ifdef Q_CC_MSVC
// we provide a buffer that can hold any int value: // we provide a buffer that can hold any int value:
char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-' char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-'
@ -3538,9 +3539,10 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
*ok = false; *ok = false;
return 0; return 0;
} }
size = strlen(buffer);
#else #else
const char * const buffer = ::getenv(varName); const char * const buffer = ::getenv(varName);
if (!buffer || strlen(buffer) > MaxDigitsForOctalInt + 2) { if (!buffer || (size = strlen(buffer)) > MaxDigitsForOctalInt + 2) {
if (ok) if (ok)
*ok = false; *ok = false;
return 0; return 0;
@ -3548,7 +3550,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
#endif #endif
bool ok_ = true; bool ok_ = true;
const char *endptr; const char *endptr;
const qlonglong value = qstrtoll(buffer, &endptr, 0, &ok_); const qlonglong value = qstrntoll(buffer, size, &endptr, 0, &ok_);
// Keep the following checks in sync with QByteArray::toInt() // Keep the following checks in sync with QByteArray::toInt()
if (!ok_) { if (!ok_) {

View File

@ -1,5 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -86,6 +87,7 @@ static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptL
{ {
address = 0; address = 0;
int dotCount = 0; int dotCount = 0;
const char *const stop = ptr + qstrlen(ptr);
while (dotCount < 4) { while (dotCount < 4) {
if (!acceptLeadingZero && *ptr == '0' && if (!acceptLeadingZero && *ptr == '0' &&
ptr[1] != '.' && ptr[1] != '\0') ptr[1] != '.' && ptr[1] != '\0')
@ -93,7 +95,7 @@ static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptL
const char *endptr; const char *endptr;
bool ok; bool ok;
quint64 ll = qstrtoull(ptr, &endptr, 0, &ok); quint64 ll = qstrntoull(ptr, stop - ptr, &endptr, 0, &ok);
quint32 x = ll; quint32 x = ll;
if (!ok || endptr == ptr || ll != x) if (!ok || endptr == ptr || ll != x)
return false; return false;
@ -158,6 +160,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
return ret; return ret;
const char *ptr = buffer.data(); const char *ptr = buffer.data();
const char *const stop = ptr + buffer.size();
// count the colons // count the colons
int colonCount = 0; int colonCount = 0;
@ -213,7 +216,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
const char *endptr; const char *endptr;
bool ok; bool ok;
quint64 ll = qstrtoull(ptr, &endptr, 16, &ok); quint64 ll = qstrntoull(ptr, stop - ptr, &endptr, 16, &ok);
quint16 x = ll; quint16 x = ll;
// Reject malformed fields: // Reject malformed fields:

View File

@ -467,7 +467,7 @@ inline bool QStorageIterator::next()
if (fgets(ptr, buffer.size(), fp) == nullptr) if (fgets(ptr, buffer.size(), fp) == nullptr)
return false; return false;
size_t len = strlen(buffer.data()); size_t len = strlen(ptr);
if (len == 0) if (len == 0)
return false; return false;
while (Q_UNLIKELY(ptr[len - 1] != '\n' && !feof(fp))) { while (Q_UNLIKELY(ptr[len - 1] != '\n' && !feof(fp))) {
@ -482,27 +482,28 @@ inline bool QStorageIterator::next()
Q_ASSERT(len < size_t(buffer.size())); Q_ASSERT(len < size_t(buffer.size()));
} }
ptr[len - 1] = '\0'; ptr[len - 1] = '\0';
const char *const stop = ptr + len - 1;
// parse the line // parse the line
bool ok; bool ok;
mnt.mnt_freq = 0; mnt.mnt_freq = 0;
mnt.mnt_passno = 0; mnt.mnt_passno = 0;
mnt.mount_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); mnt.mount_id = qstrntoll(ptr, stop - ptr, const_cast<const char **>(&ptr), 10, &ok);
if (!ok) if (!ok)
return false; return false;
int parent_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); int parent_id = qstrntoll(ptr, stop - ptr, const_cast<const char **>(&ptr), 10, &ok);
Q_UNUSED(parent_id); Q_UNUSED(parent_id);
if (!ok) if (!ok)
return false; return false;
int rdevmajor = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); int rdevmajor = qstrntoll(ptr, stop - ptr, const_cast<const char **>(&ptr), 10, &ok);
if (!ok) if (!ok)
return false; return false;
if (*ptr != ':') if (*ptr != ':')
return false; return false;
int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok); int rdevminor = qstrntoll(ptr + 1, stop - ptr - 1, const_cast<const char **>(&ptr), 10, &ok);
if (!ok) if (!ok)
return false; return false;
mnt.rdev = makedev(rdevmajor, rdevminor); mnt.rdev = makedev(rdevmajor, rdevminor);

View File

@ -223,7 +223,7 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, cha
// This is why the final decimal point is offset by 1, relative to the number after 'e'. // This is why the final decimal point is offset by 1, relative to the number after 'e'.
bool ok; bool ok;
const char *endptr; const char *endptr;
decpt = qstrtoll(target.data() + eSign + 1, &endptr, 10, &ok) + 1; decpt = qstrntoll(target.data() + eSign + 1, length - eSign - 1, &endptr, 10, &ok) + 1;
Q_ASSERT(ok); Q_ASSERT(ok);
Q_ASSERT(endptr - target.data() <= length); Q_ASSERT(endptr - target.data() <= length);
} else { } else {

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -982,7 +982,7 @@ static QString winIso639LangName(LCID id)
const char *endptr; const char *endptr;
bool ok; bool ok;
QByteArray latin1_lang_code = std::move(lang_code).toLatin1(); QByteArray latin1_lang_code = std::move(lang_code).toLatin1();
int i = qstrtoull(latin1_lang_code, &endptr, 16, &ok); int i = qstrntoull(latin1_lang_code.data(), latin1_lang_code.size(), &endptr, 16, &ok);
if (ok && *endptr == '\0') { if (ok && *endptr == '\0') {
switch (i) { switch (i) {
case 0x814: case 0x814:
@ -1024,7 +1024,7 @@ static QByteArray getWinLocaleName(LCID id)
if (result == "C" if (result == "C"
|| (!result.isEmpty() && qt_splitLocaleName(QString::fromLocal8Bit(result)))) { || (!result.isEmpty() && qt_splitLocaleName(QString::fromLocal8Bit(result)))) {
bool ok = false; // See if we have a Windows locale code instead of a locale name: bool ok = false; // See if we have a Windows locale code instead of a locale name:
long id = qstrtoll(result.data(), 0, 0, &ok); long id = qstrntoll(result.data(), result.size(), 0, 0, &ok);
if (!ok || id == 0 || id < INT_MIN || id > INT_MAX) // Assume real locale name if (!ok || id == 0 || id < INT_MIN || id > INT_MAX) // Assume real locale name
return result; return result;
return winLangCodeToIsoName(int(id)); return winLangCodeToIsoName(int(id));

View File

@ -6608,17 +6608,19 @@ static uint parse_flag_characters(const char * &c) noexcept
} }
} }
static int parse_field_width(const char * &c) static int parse_field_width(const char *&c, qsizetype size)
{ {
Q_ASSERT(qIsDigit(*c)); Q_ASSERT(qIsDigit(*c));
const char *const stop = c + size;
// can't be negative - started with a digit // can't be negative - started with a digit
// contains at least one digit // contains at least one digit
const char *endp; const char *endp;
bool ok; bool ok;
const qulonglong result = qstrtoull(c, &endp, 10, &ok); const qulonglong result = qstrntoull(c, size, &endp, 10, &ok);
c = endp; c = endp;
while (qIsDigit(*c)) // preserve Qt 5.5 behavior of consuming all digits, no matter how many // preserve Qt 5.5 behavior of consuming all digits, no matter how many
while (c < stop && qIsDigit(*c))
++c; ++c;
return ok && result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0; return ok && result < qulonglong(std::numeric_limits<int>::max()) ? int(result) : 0;
} }
@ -6674,6 +6676,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
QString result; QString result;
const char *c = cformat; const char *c = cformat;
const char *formatEnd = cformat + qstrlen(cformat);
for (;;) { for (;;) {
// Copy non-escape chars to result // Copy non-escape chars to result
const char *cb = c; const char *cb = c;
@ -6708,7 +6711,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
// Parse field width // Parse field width
int width = -1; // -1 means unspecified int width = -1; // -1 means unspecified
if (qIsDigit(*c)) { if (qIsDigit(*c)) {
width = parse_field_width(c); width = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least } else if (*c == '*') { // can't parse this in another function, not portably, at least
width = va_arg(ap, int); width = va_arg(ap, int);
if (width < 0) if (width < 0)
@ -6726,7 +6729,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
if (*c == '.') { if (*c == '.') {
++c; ++c;
if (qIsDigit(*c)) { if (qIsDigit(*c)) {
precision = parse_field_width(c); precision = parse_field_width(c, formatEnd - c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least } else if (*c == '*') { // can't parse this in another function, not portably, at least
precision = va_arg(ap, int); precision = va_arg(ap, int);
if (precision < 0) if (precision < 0)

View File

@ -419,23 +419,17 @@ static int parsePosixTime(const char *begin, const char *end)
// Format "hh[:mm[:ss]]" // Format "hh[:mm[:ss]]"
int hour, min = 0, sec = 0; int hour, min = 0, sec = 0;
// Note that the calls to qstrtoll do *not* check against the end pointer,
// which means they proceed until they find a non-digit. We check that we're
// still in range at the end, but we may have read past end. It's the
// caller's responsibility to ensure that begin is part of a null-terminated
// string.
const int maxHour = 137; // POSIX's extended range. const int maxHour = 137; // POSIX's extended range.
bool ok = false; bool ok = false;
const char *cut = begin; const char *cut = begin;
hour = qstrtoll(begin, &cut, 10, &ok); hour = qstrntoll(begin, end - begin, &cut, 10, &ok);
if (!ok || hour < -maxHour || hour > maxHour || cut > begin + 2) if (!ok || hour < -maxHour || hour > maxHour || cut > begin + 2)
return INT_MIN; return INT_MIN;
begin = cut; begin = cut;
if (begin < end && *begin == ':') { if (begin < end && *begin == ':') {
// minutes // minutes
++begin; ++begin;
min = qstrtoll(begin, &cut, 10, &ok); min = qstrntoll(begin, end - begin, &cut, 10, &ok);
if (!ok || min < 0 || min > 59 || cut > begin + 2) if (!ok || min < 0 || min > 59 || cut > begin + 2)
return INT_MIN; return INT_MIN;
@ -443,7 +437,7 @@ static int parsePosixTime(const char *begin, const char *end)
if (begin < end && *begin == ':') { if (begin < end && *begin == ':') {
// seconds // seconds
++begin; ++begin;
sec = qstrtoll(begin, &cut, 10, &ok); sec = qstrntoll(begin, end - begin, &cut, 10, &ok);
if (!ok || sec < 0 || sec > 59 || cut > begin + 2) if (!ok || sec < 0 || sec > 59 || cut > begin + 2)
return INT_MIN; return INT_MIN;
begin = cut; begin = cut;

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com> ** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
@ -465,7 +465,7 @@ QVersionNumber QVersionNumber::fromString(QLatin1String string, int *suffixIndex
do { do {
bool ok = false; bool ok = false;
const qulonglong value = qstrtoull(start, &end, 10, &ok); const qulonglong value = qstrntoull(start, endOfString - start, &end, 10, &ok);
if (!ok || value > qulonglong(std::numeric_limits<int>::max())) if (!ok || value > qulonglong(std::numeric_limits<int>::max()))
break; break;
seg.append(int(value)); seg.append(int(value));