Make sure $$relative_path() uses an absolute path as its first arg

Thanks to QTBUG-61373, this qmake function was called with
/usr/local/5.10.1 as baseDir, which isn't absolute, leading to an
assertion failure.  We could raise the error within qmake but it
proved easier to simply resolve any non-absolute baseDir using PWD,
before trying to use it as an absolute path.

Did the same for $$absolute_path().  Documented both.  Adjusted the
assert that caught this to report any non-absolute path that upsets
it.  Added simple tests, fixed an existing test.

Task-number: QTBUG-66156
Change-Id: Icfef2e2f5b236e071177c9beffa38d71bf404292
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Edward Welbourne 2018-03-02 12:30:44 +01:00
parent ee54df0311
commit 58b373c9e3
4 changed files with 32 additions and 9 deletions

View File

@ -2913,7 +2913,8 @@
Returns the absolute path of \c path.
If \c base is not specified, uses the current directory as the base
directory.
directory. If it is a relative path, it is resolved relative to the current
directory before use.
For example, the following call returns the string
\c {"/home/johndoe/myproject/readme.txt"}:
@ -3152,9 +3153,15 @@
\section2 relative_path(filePath[, base])
Returns the path to \c filePath relative to \c base. If \c base is not
specified, it is the current project directory. This function is a wrapper
around QDir::relativeFilePath.
Returns the path to \c filePath relative to \c base.
If \c base is not specified, it is the current project
directory. If it is relative, it is resolved relative to the
current project directory before use.
If \c filePath is relative, it is first resolved against the base
directory; in that case, this function effectively acts as
$$clean_path().
See also \l{absolute_path(path[, base])}{absolute_path()},
\l{clean_path(path)}{clean_path()}.

View File

@ -103,7 +103,7 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(fileName);
#ifdef Q_OS_WIN // Add drive to otherwise-absolute path:
if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') {
Q_ASSERT(isAbsolutePath(baseDir));
Q_ASSERT_X(isAbsolutePath(baseDir), "IoUtils::resolvePath", qUtf8Printable(baseDir));
return QDir::cleanPath(baseDir.left(2) + fileName);
}
#endif // Q_OS_WIN

View File

@ -1178,7 +1178,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
QString baseDir = args.count() > 1
? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
: currentDirectory();
QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
ret << (rstr.isSharedWith(m_tmp1)
? args.at(0)
@ -1192,7 +1194,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
QString baseDir = args.count() > 1
? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
: currentDirectory();
QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
QString rstr = QDir(baseDir).relativeFilePath(absArg);
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));

View File

@ -1604,6 +1604,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
QTest::newRow("$$absolute_path(): relative file & relative path")
<< "VAR = $$absolute_path(dir/file.ext, some/where)"
<< "VAR = " + qindir + "/some/where/dir/file.ext"
<< ""
<< true;
QTest::newRow("$$absolute_path(): file & path")
<< "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)"
<< "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext"
@ -1642,6 +1648,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
QTest::newRow("$$relative_path(): relative file & relative path")
<< "VAR = $$relative_path(dir/file.ext, some/where)"
<< "VAR = dir/file.ext"
<< ""
<< true;
QTest::newRow("$$relative_path(): relative file to empty")
<< "VAR = $$relative_path(dir/..)"
<< "VAR = ."
@ -2752,9 +2764,9 @@ void tst_qmakelib::proEval_data()
// Raw data leak with empty file name. Verify with Valgrind or asan.
QTest::newRow("QTBUG-54550")
<< "FULL = /there/is\n"
<< "FULL = " EVAL_DRIVE "/there/is\n"
"VAR = $$absolute_path(, $$FULL/nothing/here/really)"
<< "VAR = /there/is/nothing/here/really"
<< "VAR = " EVAL_DRIVE "/there/is/nothing/here/really"
<< ""
<< true;
}