Unify QByteArray::MaxSize and MaxAllocSize
We have established the maximum size qAllocMore can deal with in commit880986be23
and we should use it. The maximum size for byte arrays is reduced by one byte as with the previous code we could make qAllocMore produce ((1 << 31) - extra) by passing (1 << 30). That is not a problem for qAllocMore itself (as long as extra > 0) but it's hard to verify that no related code casts the total sum back to signed int, which would overflow to -1. To make the compiler inline access to the maximum size, a private enum MaxByteArraySize is provided, which can be used in internal code. This fixes the merge of commits880986be23
andc70658d301
Change-Id: Idb04856f7c2e53ef383063e7555d3083020ff2b7 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
8d5516b585
commit
ef0f7f4248
@ -39,6 +39,7 @@
|
|||||||
#include "qfile.h"
|
#include "qfile.h"
|
||||||
#include "qstringlist.h"
|
#include "qstringlist.h"
|
||||||
#include "qdir.h"
|
#include "qdir.h"
|
||||||
|
#include "private/qbytearray_p.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -941,9 +942,9 @@ QByteArray QIODevice::read(qint64 maxSize)
|
|||||||
Q_UNUSED(d);
|
Q_UNUSED(d);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (quint64(maxSize) >= QByteArray::MaxSize) {
|
if (maxSize >= MaxByteArraySize) {
|
||||||
checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit");
|
checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit");
|
||||||
maxSize = QByteArray::MaxSize - 1;
|
maxSize = MaxByteArraySize - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 readBytes = 0;
|
qint64 readBytes = 0;
|
||||||
@ -995,7 +996,7 @@ QByteArray QIODevice::readAll()
|
|||||||
|
|
||||||
// flush internal read buffer
|
// flush internal read buffer
|
||||||
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
|
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
|
||||||
if (quint64(d->buffer.size()) >= QByteArray::MaxSize)
|
if (d->buffer.size() >= MaxByteArraySize)
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
result = d->buffer.readAll();
|
result = d->buffer.readAll();
|
||||||
readBytes = result.size();
|
readBytes = result.size();
|
||||||
@ -1008,7 +1009,7 @@ QByteArray QIODevice::readAll()
|
|||||||
// Size is unknown, read incrementally.
|
// Size is unknown, read incrementally.
|
||||||
qint64 readResult;
|
qint64 readResult;
|
||||||
do {
|
do {
|
||||||
if (quint64(readBytes) + QIODEVICE_BUFFERSIZE >= QByteArray::MaxSize) {
|
if (readBytes + QIODEVICE_BUFFERSIZE >= MaxByteArraySize) {
|
||||||
// If resize would fail, don't read more, return what we have.
|
// If resize would fail, don't read more, return what we have.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1020,7 +1021,7 @@ QByteArray QIODevice::readAll()
|
|||||||
} else {
|
} else {
|
||||||
// Read it all in one go.
|
// Read it all in one go.
|
||||||
// If resize fails, don't read anything.
|
// If resize fails, don't read anything.
|
||||||
if (quint64(readBytes + theSize - d->pos) >= QByteArray::MaxSize)
|
if (readBytes + theSize - d->pos >= MaxByteArraySize)
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
result.resize(int(readBytes + theSize - d->pos));
|
result.resize(int(readBytes + theSize - d->pos));
|
||||||
readBytes += read(result.data() + readBytes, result.size() - readBytes);
|
readBytes += read(result.data() + readBytes, result.size() - readBytes);
|
||||||
@ -1178,9 +1179,9 @@ QByteArray QIODevice::readLine(qint64 maxSize)
|
|||||||
Q_UNUSED(d);
|
Q_UNUSED(d);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (quint64(maxSize) >= QByteArray::MaxSize) {
|
if (maxSize >= MaxByteArraySize) {
|
||||||
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
|
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
|
||||||
maxSize = QByteArray::MaxSize - 1;
|
maxSize = MaxByteArraySize - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.resize(int(maxSize));
|
result.resize(int(maxSize));
|
||||||
@ -1188,7 +1189,7 @@ QByteArray QIODevice::readLine(qint64 maxSize)
|
|||||||
if (!result.size()) {
|
if (!result.size()) {
|
||||||
// If resize fails or maxSize == 0, read incrementally
|
// If resize fails or maxSize == 0, read incrementally
|
||||||
if (maxSize == 0)
|
if (maxSize == 0)
|
||||||
maxSize = QByteArray::MaxSize - 1;
|
maxSize = MaxByteArraySize - 1;
|
||||||
|
|
||||||
// The first iteration needs to leave an extra byte for the terminating null
|
// The first iteration needs to leave an extra byte for the terminating null
|
||||||
result.resize(1);
|
result.resize(1);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "qlocale_p.h"
|
#include "qlocale_p.h"
|
||||||
#include "qstringalgorithms_p.h"
|
#include "qstringalgorithms_p.h"
|
||||||
#include "qscopedpointer.h"
|
#include "qscopedpointer.h"
|
||||||
|
#include "qbytearray_p.h"
|
||||||
#include <qdatastream.h>
|
#include <qdatastream.h>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
|
||||||
@ -123,8 +124,8 @@ int qFindByteArray(
|
|||||||
|
|
||||||
int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
|
int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
Q_ASSERT(alloc >= 0 && extra >= 0);
|
Q_ASSERT(alloc >= 0 && extra >= 0 && extra <= MaxAllocSize);
|
||||||
Q_ASSERT_X(uint(alloc) <= QByteArray::MaxSize, "qAllocMore", "Requested size is too large!");
|
Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!");
|
||||||
|
|
||||||
unsigned nalloc = qNextPowerOfTwo(alloc + extra);
|
unsigned nalloc = qNextPowerOfTwo(alloc + extra);
|
||||||
|
|
||||||
@ -837,16 +838,6 @@ static inline char qToLower(char c)
|
|||||||
\sa QString, QBitArray
|
\sa QString, QBitArray
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\variable QByteArray::MaxSize
|
|
||||||
\internal
|
|
||||||
\since 5.4
|
|
||||||
|
|
||||||
The maximum size of a QByteArray (including a '\0' terminator), in bytes.
|
|
||||||
Also applies to the maximum storage size of QString and QVector, though
|
|
||||||
not the number of elements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\enum QByteArray::Base64Option
|
\enum QByteArray::Base64Option
|
||||||
\since 5.2
|
\since 5.2
|
||||||
@ -1575,7 +1566,7 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options)
|
|||||||
d = x;
|
d = x;
|
||||||
} else {
|
} else {
|
||||||
if (options & Data::Grow) {
|
if (options & Data::Grow) {
|
||||||
if (alloc > uint(MaxAllocSize) - uint(sizeof(Data)))
|
if (alloc > MaxByteArraySize)
|
||||||
qBadAlloc();
|
qBadAlloc();
|
||||||
alloc = qAllocMore(alloc, sizeof(Data));
|
alloc = qAllocMore(alloc, sizeof(Data));
|
||||||
}
|
}
|
||||||
|
@ -162,9 +162,6 @@ private:
|
|||||||
typedef QTypedArrayData<char> Data;
|
typedef QTypedArrayData<char> Data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// undocumented:
|
|
||||||
static const quint64 MaxSize = (1 << 30) - sizeof(Data);
|
|
||||||
|
|
||||||
enum Base64Option {
|
enum Base64Option {
|
||||||
Base64Encoding = 0,
|
Base64Encoding = 0,
|
||||||
Base64UrlEncoding = 1,
|
Base64UrlEncoding = 1,
|
||||||
|
61
src/corelib/tools/qbytearray_p.h
Normal file
61
src/corelib/tools/qbytearray_p.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QBYTEARRAY_P_H
|
||||||
|
#define QBYTEARRAY_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists for the convenience
|
||||||
|
// of other Qt classes. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QtCore/qbytearray.h>
|
||||||
|
#include <QtCore/qtypetraits.h>
|
||||||
|
#include "qtools_p.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// Define as enum to force inlining. Don't expose MaxAllocSize in a public header.
|
||||||
|
MaxByteArraySize = MaxAllocSize - sizeof(QtPrivate::remove_pointer<QByteArray::DataPtr>::type)
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QBYTEARRAY_P_H
|
@ -33,6 +33,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "private/qringbuffer_p.h"
|
#include "private/qringbuffer_p.h"
|
||||||
|
#include "private/qbytearray_p.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -79,7 +80,7 @@ void QRingBuffer::free(qint64 bytes)
|
|||||||
clear(); // try to minify/squeeze us
|
clear(); // try to minify/squeeze us
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
Q_ASSERT(bytes < MaxByteArraySize);
|
||||||
head += int(bytes);
|
head += int(bytes);
|
||||||
bufferSize -= bytes;
|
bufferSize -= bytes;
|
||||||
}
|
}
|
||||||
@ -96,14 +97,14 @@ void QRingBuffer::free(qint64 bytes)
|
|||||||
|
|
||||||
char *QRingBuffer::reserve(qint64 bytes)
|
char *QRingBuffer::reserve(qint64 bytes)
|
||||||
{
|
{
|
||||||
if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
|
if (bytes <= 0 || bytes >= MaxByteArraySize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const qint64 newSize = bytes + tail;
|
const qint64 newSize = bytes + tail;
|
||||||
// if need buffer reallocation
|
// if need buffer reallocation
|
||||||
if (newSize > buffers.last().size()) {
|
if (newSize > buffers.last().size()) {
|
||||||
if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
|
if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
|
||||||
|| quint64(newSize) >= QByteArray::MaxSize)) {
|
|| newSize >= MaxByteArraySize)) {
|
||||||
// shrink this buffer to its current size
|
// shrink this buffer to its current size
|
||||||
buffers.last().resize(tail);
|
buffers.last().resize(tail);
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ char *QRingBuffer::reserve(qint64 bytes)
|
|||||||
|
|
||||||
char *writePtr = buffers.last().data() + tail;
|
char *writePtr = buffers.last().data() + tail;
|
||||||
bufferSize += bytes;
|
bufferSize += bytes;
|
||||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
Q_ASSERT(bytes < MaxByteArraySize);
|
||||||
tail += int(bytes);
|
tail += int(bytes);
|
||||||
return writePtr;
|
return writePtr;
|
||||||
}
|
}
|
||||||
@ -129,7 +130,7 @@ char *QRingBuffer::reserve(qint64 bytes)
|
|||||||
*/
|
*/
|
||||||
char *QRingBuffer::reserveFront(qint64 bytes)
|
char *QRingBuffer::reserveFront(qint64 bytes)
|
||||||
{
|
{
|
||||||
if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
|
if (bytes <= 0 || bytes >= MaxByteArraySize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (head < bytes) {
|
if (head < bytes) {
|
||||||
@ -163,7 +164,7 @@ void QRingBuffer::chop(qint64 bytes)
|
|||||||
clear(); // try to minify/squeeze us
|
clear(); // try to minify/squeeze us
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
Q_ASSERT(bytes < MaxByteArraySize);
|
||||||
tail -= int(bytes);
|
tail -= int(bytes);
|
||||||
bufferSize -= bytes;
|
bufferSize -= bytes;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ HEADERS += \
|
|||||||
tools/qarraydatapointer.h \
|
tools/qarraydatapointer.h \
|
||||||
tools/qbitarray.h \
|
tools/qbitarray.h \
|
||||||
tools/qbytearray.h \
|
tools/qbytearray.h \
|
||||||
|
tools/qbytearray_p.h \
|
||||||
tools/qbytearraylist.h \
|
tools/qbytearraylist.h \
|
||||||
tools/qbytearraymatcher.h \
|
tools/qbytearraymatcher.h \
|
||||||
tools/qbytedata_p.h \
|
tools/qbytedata_p.h \
|
||||||
|
Loading…
Reference in New Issue
Block a user