Fix wrong behavior when reading text

Also add another 'file read error' status.

Closes #19254.
PR #19262.
This commit is contained in:
Chocobo1 2023-07-02 13:23:20 +08:00 committed by GitHub
parent 08a771468d
commit 80791e328d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 11 deletions

2
.gitattributes vendored
View file

@ -5,3 +5,5 @@ core.eol=lf
*.png binary *.png binary
*.qm binary *.qm binary
*.zip binary *.zip binary
test/testdata/crlf.txt text eol=crlf

View file

@ -33,19 +33,19 @@ repos:
args: ["--fix=lf"] args: ["--fix=lf"]
exclude: | exclude: |
(?x)^( (?x)^(
compile_commands.json |
src/webui/www/private/css/lib/.* | src/webui/www/private/css/lib/.* |
src/webui/www/private/scripts/lib/.* src/webui/www/private/scripts/lib/.* |
test/testdata/crlf.txt
)$ )$
- id: end-of-file-fixer - id: end-of-file-fixer
name: Check trailing newlines name: Check trailing newlines
exclude: | exclude: |
(?x)^( (?x)^(
compile_commands.json |
configure | configure |
src/webui/www/private/css/lib/.* | src/webui/www/private/css/lib/.* |
src/webui/www/private/scripts/lib/.* src/webui/www/private/scripts/lib/.* |
test/testdata/crlf.txt
)$ )$
exclude_types: exclude_types:
- svg - svg

View file

@ -89,16 +89,37 @@ nonstd::expected<QByteArray, Utils::IO::ReadError> Utils::IO::readFile(const Pat
return nonstd::make_unexpected(ReadError {ReadError::ExceedSize, message}); return nonstd::make_unexpected(ReadError {ReadError::ExceedSize, message});
} }
// Do not use `QIODevice::readAll()` it won't stop when reading `/dev/zero` #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
const QByteArray data = file.read(fileSize); QByteArray ret {fileSize, Qt::Uninitialized};
if (const qint64 dataSize = data.size(); dataSize != fileSize) #else
QByteArray ret {static_cast<int>(fileSize), Qt::Uninitialized};
#endif
const qint64 actualSize = file.read(ret.data(), fileSize);
if (actualSize < 0)
{ {
const QString message = QCoreApplication::translate("Utils::IO", "Read size mismatch. File: \"%1\". Expected: %2. Actual: %3") const QString message = QCoreApplication::translate("Utils::IO", "File read error. File: \"%1\". Error: \"%2\"")
.arg(file.fileName(), QString::number(fileSize), QString::number(dataSize)); .arg(file.fileName(), file.errorString());
return nonstd::make_unexpected(ReadError {ReadError::SizeMismatch, message}); return nonstd::make_unexpected(ReadError {ReadError::Failed, message});
} }
return data; if (actualSize < fileSize)
{
// `QIODevice::Text` will convert CRLF to LF on-the-fly and affects return value
// of `qint64 QIODevice::read(char *data, qint64 maxSize)`
if (additionalMode.testFlag(QIODevice::Text))
{
ret.truncate(actualSize);
}
else
{
const QString message = QCoreApplication::translate("Utils::IO", "Read size mismatch. File: \"%1\". Expected: %2. Actual: %3")
.arg(file.fileName(), QString::number(fileSize), QString::number(actualSize));
return nonstd::make_unexpected(ReadError {ReadError::SizeMismatch, message});
}
}
return ret;
} }
nonstd::expected<void, QString> Utils::IO::saveToFile(const Path &path, const QByteArray &data) nonstd::expected<void, QString> Utils::IO::saveToFile(const Path &path, const QByteArray &data)

View file

@ -89,6 +89,7 @@ namespace Utils::IO
{ {
NotExist, NotExist,
ExceedSize, ExceedSize,
Failed, // `read()` operation failed
SizeMismatch SizeMismatch
}; };

View file

@ -516,6 +516,7 @@ void WebApplication::sendFile(const Path &path)
LogMsg(message, Log::WARNING); LogMsg(message, Log::WARNING);
throw InternalServerErrorHTTPError(readResult.error().message); throw InternalServerErrorHTTPError(readResult.error().message);
case Utils::IO::ReadError::Failed:
case Utils::IO::ReadError::SizeMismatch: case Utils::IO::ReadError::SizeMismatch:
LogMsg(message, Log::WARNING); LogMsg(message, Log::WARNING);
throw InternalServerErrorHTTPError(readResult.error().message); throw InternalServerErrorHTTPError(readResult.error().message);

2
test/testdata/crlf.txt vendored Normal file
View file

@ -0,0 +1,2 @@

View file

@ -77,6 +77,13 @@ private slots:
QCOMPARE(readResult.value(), size10Data); QCOMPARE(readResult.value(), size10Data);
} }
{
const Path crlfFile = testFolder / Path(u"crlf.txt"_s);
const auto readResult = Utils::IO::readFile(crlfFile, -1, QIODevice::Text);
QCOMPARE(readResult.has_value(), true);
QCOMPARE(readResult.value(), "\n\n");
}
{ {
const Path nonExistFile = testFolder / Path(u".non_existent_file_1234"_s); const Path nonExistFile = testFolder / Path(u".non_existent_file_1234"_s);
const auto readResult = Utils::IO::readFile(nonExistFile, 1); const auto readResult = Utils::IO::readFile(nonExistFile, 1);