check errno in JSC long number parser

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-06-07 21:17:03 +03:00
parent a00e666794
commit b90184e871
9 changed files with 41 additions and 38 deletions

View file

@ -76,6 +76,8 @@
#include "CurrentTime.h"
#include "CallFrame.h"
#include "qcore_unix_p.h"
#include <algorithm>
#include <limits.h>
#include <limits>
@ -522,9 +524,9 @@ static int findMonth(const char* monthStr)
static bool parseLong(const char* string, char** stopPosition, int base, long* result)
{
Q_RESET_ERRNO
*result = strtol(string, stopPosition, base);
// Avoid the use of errno as it is not available on Windows CE
if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX)
if (string == *stopPosition || ((*result == LONG_MIN || *result == LONG_MAX) && (errno == ERANGE || errno == EINVAL)))
return false;
return true;
}

View file

@ -295,7 +295,7 @@ void QFileSystemWatcherEngineUnix::readFromFd()
int r;
struct kevent kev;
struct timespec ts = { 0, 0 }; // 0 ts, because we want to poll
EINTR_LOOP(r, kevent(sockfd, 0, 0, &kev, 1, &ts));
Q_EINTR_LOOP(r, kevent(sockfd, 0, 0, &kev, 1, &ts));
if (r < 0) {
perror("QFileSystemWatcherEngineUnix: error during kevent wait");
return;

View file

@ -181,7 +181,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode)
// Seek to the end when in Append mode.
if (d->openMode & QFile::Append) {
int ret;
EINTR_LOOP(ret, QT_LSEEK(d->fd, 0, SEEK_END));
Q_EINTR_LOOP(ret, QT_LSEEK(d->fd, 0, SEEK_END));
if (ret == -1) {
setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
qt_error_string(errno));
@ -252,7 +252,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle
// Seek to the end when in Append mode.
if (d->openMode & QFile::Append) {
int ret;
EINTR_LOOP(ret, QT_LSEEK(d->fd, 0, SEEK_END));
Q_EINTR_LOOP(ret, QT_LSEEK(d->fd, 0, SEEK_END));
if (ret == -1) {
setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
qt_error_string(errno));

View file

@ -40,11 +40,21 @@
#include <sys/wait.h>
#include <errno.h>
#define EINTR_LOOP(var, cmd) \
#define Q_EINTR_LOOP(var, cmd) \
do { \
var = cmd; \
} while (var == -1 && errno == EINTR)
// BSD and musl libc implementations do not reset errno and there is no
// reliable way to check if some functions (e.g. strtoll()) errored or returned
// a valid value if they do not reset errno
#ifdef __GLIBC__
# define Q_RESET_ERRNO
#else
# define Q_RESET_ERRNO errno = 0;
#endif
QT_BEGIN_NAMESPACE
// Internal operator functions for timevals
@ -115,7 +125,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07
flags |= O_CLOEXEC;
#endif
int fd;
EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
Q_EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
#ifndef O_CLOEXEC
// unknown flags are ignored, so we have no way of verifying if
@ -174,7 +184,7 @@ static inline int qt_safe_dup(int oldfd)
static inline int qt_safe_dup2(int oldfd, int newfd)
{
int ret;
EINTR_LOOP(ret, ::dup2(oldfd, newfd));
Q_EINTR_LOOP(ret, ::dup2(oldfd, newfd));
return ret;
}
@ -182,7 +192,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd)
static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
{
qint64 ret = 0;
EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
Q_EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
return ret;
}
@ -190,7 +200,7 @@ static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
{
qint64 ret = 0;
EINTR_LOOP(ret, QT_WRITE(fd, data, len));
Q_EINTR_LOOP(ret, QT_WRITE(fd, data, len));
return ret;
}
@ -204,7 +214,7 @@ static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len
static inline int qt_safe_creat(const char* path, mode_t flags)
{
int ret;
EINTR_LOOP(ret, QT_CREAT(path, flags));
Q_EINTR_LOOP(ret, QT_CREAT(path, flags));
return ret;
}
@ -212,7 +222,7 @@ static inline int qt_safe_creat(const char* path, mode_t flags)
static inline int qt_safe_close(int fd)
{
int ret;
EINTR_LOOP(ret, QT_CLOSE(fd));
Q_EINTR_LOOP(ret, QT_CLOSE(fd));
return ret;
}
@ -221,7 +231,7 @@ static inline int qt_safe_execve(const char *filename, char *const argv[],
char *const envp[])
{
int ret;
EINTR_LOOP(ret, ::execve(filename, argv, envp));
Q_EINTR_LOOP(ret, ::execve(filename, argv, envp));
return ret;
}
@ -229,7 +239,7 @@ static inline int qt_safe_execve(const char *filename, char *const argv[],
static inline int qt_safe_execv(const char *path, char *const argv[])
{
int ret;
EINTR_LOOP(ret, ::execv(path, argv));
Q_EINTR_LOOP(ret, ::execv(path, argv));
return ret;
}
@ -237,7 +247,7 @@ static inline int qt_safe_execv(const char *path, char *const argv[])
static inline int qt_safe_execvp(const char *file, char *const argv[])
{
int ret;
EINTR_LOOP(ret, ::execvp(file, argv));
Q_EINTR_LOOP(ret, ::execvp(file, argv));
return ret;
}
@ -245,7 +255,7 @@ static inline int qt_safe_execvp(const char *file, char *const argv[])
static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
{
pid_t ret;
EINTR_LOOP(ret, ::waitpid(pid, status, options));
Q_EINTR_LOOP(ret, ::waitpid(pid, status, options));
return ret;
}

View file

@ -125,7 +125,7 @@ bool QSharedMemoryPrivate::create(int size)
QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
int fd;
EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666));
Q_EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666));
if (fd == -1) {
QString function = QLatin1String("QSharedMemory::create");
switch (errno) {
@ -142,7 +142,7 @@ bool QSharedMemoryPrivate::create(int size)
// the size may only be set once; ignore errors
int ret;
EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
Q_EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
if (ret == -1) {
setErrorString(QLatin1String("QSharedMemory::create (ftruncate)"));
qt_safe_close(fd);
@ -161,7 +161,7 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
mode_t omode = (mode == QSharedMemory::ReadOnly ? 0444 : 0660);
EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
Q_EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
if (hand == -1) {
QString function = QLatin1String("QSharedMemory::attach (shm_open)");
switch (errno) {

View file

@ -198,7 +198,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
// rollback changes to preserve the SysV semaphore behavior
for ( ; cnt < count; ++cnt) {
int res;
EINTR_LOOP(res, ::sem_wait(semaphore));
Q_EINTR_LOOP(res, ::sem_wait(semaphore));
}
return false;
}
@ -206,7 +206,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
} while (cnt > 0);
} else {
int res;
EINTR_LOOP(res, ::sem_wait(semaphore));
Q_EINTR_LOOP(res, ::sem_wait(semaphore));
if (res == -1) {
// If the semaphore was removed be nice and create it and then modifySemaphore again
if (errno == EINVAL || errno == EIDRM) {

View file

@ -34,8 +34,8 @@
#include "qlocale_data_p.h"
#include "qdebug.h"
#include "qcorecommon_p.h"
#include "qcore_unix_p.h"
#include <errno.h>
#include <unicode/ulocdata.h>
// #define QLOCALE_DEBUG
@ -45,15 +45,6 @@
# define QLOCALEDEBUG if (false) qDebug()
#endif
// BSD and musl libc implementations do not reset errno and there is no
// reliable way to check if some functions (e.g. strtoll()) errored or returned
// a valid value if they do not reset errno
#ifdef __GLIBC__
# define QLOCALE_RESET_ERRNO
#else
# define QLOCALE_RESET_ERRNO errno = 0;
#endif
QT_BEGIN_NAMESPACE
static const qint16 systemLocaleIndex = localeTblSize + 1;
@ -2738,7 +2729,7 @@ double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok)
}
char *endptr;
QLOCALE_RESET_ERRNO
Q_RESET_ERRNO
double ret = std::strtod(num, &endptr);
if ((ret == 0.0l && errno == ERANGE) || ret == HUGE_VAL || ret == -HUGE_VAL) {
if (ok != Q_NULLPTR)
@ -2767,7 +2758,7 @@ qlonglong QLocalePrivate::bytearrayToLongLong(const char *num, int base, bool *o
}
char *endptr;
QLOCALE_RESET_ERRNO
Q_RESET_ERRNO
qlonglong ret = std::strtoll(num, &endptr, base);
if ((ret == LLONG_MIN || ret == LLONG_MAX) && (errno == ERANGE || errno == EINVAL)) {
if (ok != Q_NULLPTR)
@ -2796,7 +2787,7 @@ qulonglong QLocalePrivate::bytearrayToUnsLongLong(const char *num, int base, boo
}
char *endptr;
QLOCALE_RESET_ERRNO
Q_RESET_ERRNO
qulonglong ret = std::strtoull(num, &endptr, base);
if (ret == ULLONG_MAX && (errno == ERANGE || errno == EINVAL)) {
if (ok != Q_NULLPTR)

View file

@ -735,7 +735,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
// well be 0, so we can't check recvfrom's return value.
ssize_t readBytes;
char c;
EINTR_LOOP(readBytes, ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize));
Q_EINTR_LOOP(readBytes, ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize));
// If there's no error, or if our buffer was too small, there must be a
// pending datagram.
@ -785,7 +785,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
ssize_t recvFromResult = 0;
char c;
EINTR_LOOP(recvFromResult, ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
Q_EINTR_LOOP(recvFromResult, ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
0, &aa.a, &sz));
if (recvFromResult == -1) {

View file

@ -76,7 +76,7 @@ static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SO
{
int ret;
// Solaris e.g. expects a non-const 2nd parameter
EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, const_cast<struct sockaddr *>(addr), addrlen));
Q_EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, const_cast<struct sockaddr *>(addr), addrlen));
return ret;
}
@ -97,7 +97,7 @@ static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int fl
#endif
int ret;
EINTR_LOOP(ret, ::sendto(sockfd, buf, len, flags, to, tolen));
Q_EINTR_LOOP(ret, ::sendto(sockfd, buf, len, flags, to, tolen));
return ret;
}