summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/qglobal.cpp5
-rw-r--r--src/corelib/tools/qlocale_tools.cpp265
-rw-r--r--tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp6
3 files changed, 61 insertions, 215 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 7913af3103..ac2f72d573 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -3127,11 +3127,14 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
return 0;
}
#endif
- const qlonglong value = qstrtoll(buffer, Q_NULLPTR, 0, ok);
+ bool ok_ = true;
+ const qlonglong value = qstrtoll(buffer, Q_NULLPTR, 0, &ok_);
if (int(value) != value) { // this is the check in QByteArray::toInt(), keep it in sync
if (ok)
*ok = false;
return 0;
+ } else if (ok) {
+ *ok = ok_;
}
return int(value);
}
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
index 56ac8fb58d..03b911c4b3 100644
--- a/src/corelib/tools/qlocale_tools.cpp
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -36,6 +37,7 @@
#include "qstring.h"
#include <ctype.h>
+#include <errno.h>
#include <float.h>
#include <limits.h>
#include <math.h>
@@ -63,6 +65,55 @@
QT_BEGIN_NAMESPACE
+#include "../../3rdparty/freebsd/strtoull.c"
+#include "../../3rdparty/freebsd/strtoll.c"
+
+unsigned long long
+qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
+{
+ // strtoull accepts negative numbers. We don't.
+ // Use a different variable so we pass the original nptr to strtoul
+ // (we need that so endptr may be nptr in case of failure)
+ const char *begin = nptr;
+ while (ascii_isspace(*begin))
+ ++begin;
+ if (*begin == '-') {
+ *ok = false;
+ return 0;
+ }
+
+ *ok = true;
+ errno = 0;
+ char *endptr2 = 0;
+ unsigned long long result = qt_strtoull(nptr, &endptr2, base);
+ if (endptr)
+ *endptr = endptr2;
+ if ((result == 0 || result == std::numeric_limits<unsigned long long>::max())
+ && (errno || endptr2 == nptr)) {
+ *ok = false;
+ return 0;
+ }
+ return result;
+}
+
+long long
+qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
+{
+ *ok = true;
+ errno = 0;
+ char *endptr2 = 0;
+ long long result = qt_strtoll(nptr, &endptr2, base);
+ if (endptr)
+ *endptr = endptr2;
+ if ((result == 0 || result == std::numeric_limits<long long>::min()
+ || result == std::numeric_limits<long long>::max())
+ && (errno || nptr == endptr2)) {
+ *ok = false;
+ return 0;
+ }
+ return result;
+}
+
static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
int *sign, char **rve, char **digits_str);
@@ -174,220 +225,6 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
return digits;
}
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgment:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-// static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
-// "$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
-
-/*
- * Convert a string to an unsigned long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-qulonglong qstrtoull(const char *nptr, const char **endptr, int base, bool *ok)
-{
- const char *s = nptr;
- qulonglong acc;
- unsigned char c;
- qulonglong qbase, cutoff;
- int any, cutlim;
-
- if (ok != 0)
- *ok = true;
-
- /*
- * See strtoq for comments as to the logic used.
- */
- s = nptr;
- do {
- c = *s++;
- } while (ascii_isspace(c));
- if (c == '-') {
- if (ok != 0)
- *ok = false;
- if (endptr != 0)
- *endptr = s - 1;
- return 0;
- } else {
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- qbase = unsigned(base);
- cutoff = qulonglong(ULLONG_MAX) / qbase;
- cutlim = qulonglong(ULLONG_MAX) % qbase;
- for (acc = 0, any = 0;; c = *s++) {
- if (!isascii(c))
- break;
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= qbase;
- acc += c;
- }
- }
- if (any == 0) {
- if (ok != 0)
- *ok = false;
- } else if (any < 0) {
- acc = ULLONG_MAX;
- if (ok != 0)
- *ok = false;
- }
- if (endptr != 0)
- *endptr = (any ? s - 1 : nptr);
- return acc;
-}
-
-
-// "$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
-
-
-/*
- * Convert a string to a long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok)
-{
- const char *s;
- qulonglong acc;
- unsigned char c;
- qulonglong qbase, cutoff;
- int neg, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- c = *s++;
- } while (ascii_isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for quads is
- * [-9223372036854775808..9223372036854775807] and the input base
- * is 10, cutoff will be set to 922337203685477580 and cutlim to
- * either 7 (neg==0) or 8 (neg==1), meaning that if we have
- * accumulated a value > 922337203685477580, or equal but the
- * next digit is > 7 (or 8), the number is too big, and we will
- * return a range error.
- *
- * Set any if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- qbase = unsigned(base);
- cutoff = neg ? qulonglong(0-(LLONG_MIN + LLONG_MAX)) + LLONG_MAX : LLONG_MAX;
- cutlim = cutoff % qbase;
- cutoff /= qbase;
- for (acc = 0, any = 0;; c = *s++) {
- if (!isascii(c))
- break;
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= qbase;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LLONG_MIN : LLONG_MAX;
- if (ok != 0)
- *ok = false;
- } else if (neg) {
- acc = (~acc) + 1;
- }
- if (endptr != 0)
- *endptr = (any >= 0 ? s - 1 : nptr);
-
- if (ok != 0)
- *ok = any > 0;
-
- return acc;
-}
-
/* From: NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp */
/* $FreeBSD: src/lib/libc/stdlib/netbsd_strtod.c,v 1.2.2.2 2001/03/02 17:14:15 tegge Exp $ */
diff --git a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
index 6d0a65da92..3e16d3b871 100644
--- a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
+++ b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
@@ -209,6 +209,12 @@ void tst_QIpAddress::invalidParseIp4_data()
// bad hex
QTest::newRow("0x1g") << "0x1g";
+ // negative numbers
+ QTest::newRow("-1") << "-1";
+ QTest::newRow("-1.1") << "-1.1";
+ QTest::newRow("1.-1") << "1.-1";
+ QTest::newRow("1.1.1.-1") << "1.1.1.-1";
+
// letters
QTest::newRow("abc") << "abc";
QTest::newRow("1.2.3a.4") << "1.2.3a.4";