File indexing completed on 2024-04-14 15:32:45
0001 /* 0002 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0003 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 #include <QTest> 0007 0008 #include <limits> 0009 0010 #include <sys/stat.h> 0011 #include <sys/types.h> 0012 #include <unistd.h> 0013 0014 #include <linuxprocmapsparser.h> 0015 0016 class LinuxProcMapsParserTest : public QObject 0017 { 0018 Q_OBJECT 0019 qulonglong m_linuxProcfsMapsInInode = 0; 0020 0021 QByteArray generateData(const QString &templatePath, qulonglong inode) 0022 { 0023 QFile f(templatePath); 0024 if (!f.open(QFile::ReadOnly)) { 0025 return {}; 0026 } 0027 QByteArray data = f.readAll(); 0028 data.replace("/__FILE_PATH__", qUtf8Printable(templatePath)); 0029 data.replace("__INODE__", QByteArray::number(inode)); 0030 return data; 0031 } 0032 0033 private Q_SLOTS: 0034 void initTestCase() 0035 { 0036 struct stat st { 0037 }; 0038 QVERIFY(stat(QFile::encodeName(QFINDTESTDATA("data/linux-procfs-maps.so")).constData(), &st) != -1); 0039 m_linuxProcfsMapsInInode = st.st_ino; 0040 } 0041 0042 void testHasDeletedStat() 0043 { 0044 // Has definitely missing files because of "(deleted)" suffix. 0045 // The exe is not actually in the fixture to prevent the function from returning early when not finding the exe. 0046 // Should this need changing in the future this needs routing through generateData(). 0047 QFile f(QFINDTESTDATA("data/linux-procfs-maps-with-missing-files")); 0048 QVERIFY(f.open(QFile::ReadOnly)); 0049 QVERIFY(LinuxProc::hasMapsDeletedFiles("/usr/bin/kwrite", f.readAll(), LinuxProc::Check::DeletedMarker)); 0050 } 0051 0052 void testNoDeletedStat() 0053 { 0054 // fixture also includes a /memfd:... path which we expect to not get reported as deleted. We do need 0055 // to substitute valid data in to get past the inode verification though. 0056 const QString templatePath = QFINDTESTDATA("data/linux-procfs-maps.so"); 0057 const QByteArray data = generateData(templatePath, m_linuxProcfsMapsInInode); 0058 QVERIFY(!LinuxProc::hasMapsDeletedFiles(templatePath, data, LinuxProc::Check::Stat)); 0059 } 0060 0061 void testBadInode() 0062 { 0063 const QString templatePath = QFINDTESTDATA("data/linux-procfs-maps.so"); 0064 const QByteArray data = generateData(templatePath, m_linuxProcfsMapsInInode - 1 /* random mutation */); 0065 QVERIFY(LinuxProc::hasMapsDeletedFiles(templatePath, data, LinuxProc::Check::Stat)); 0066 } 0067 0068 void testExecMarker() 0069 { 0070 QFile f(QFINDTESTDATA("data/linux-procfs-maps-with-deleted-exe")); 0071 QVERIFY(f.open(QFile::ReadOnly)); 0072 QVERIFY(LinuxProc::hasMapsDeletedFiles("/usr/bin/kwrite", f.readAll(), LinuxProc::Check::DeletedMarker)); 0073 } 0074 0075 void testSOMarker() 0076 { 0077 QFile f(QFINDTESTDATA("data/linux-procfs-maps-with-deleted-exe")); 0078 QVERIFY(f.open(QFile::ReadOnly)); 0079 QVERIFY(LinuxProc::hasMapsDeletedFiles("/usr/bin/kwrite", f.readAll(), LinuxProc::Check::DeletedMarker)); 0080 } 0081 0082 void testIsLibraryPath() 0083 { 0084 QVERIFY(!LinuxProc::isLibraryPath("/bin/a")); 0085 QVERIFY(!LinuxProc::isLibraryPath("/bin/a.")); 0086 0087 QVERIFY(LinuxProc::isLibraryPath("/bin/a.so")); 0088 QVERIFY(LinuxProc::isLibraryPath("/bin/a.so.0.1")); 0089 // we expect deleted modifiers to match, it keeps the regex simpler 0090 QVERIFY(LinuxProc::isLibraryPath("/bin/a.so.0.1 (deleted)")); 0091 // A bit silly but what if .so appears as a dirname 0092 QVERIFY(!LinuxProc::isLibraryPath("/bin/a.so.0/abc/foo")); 0093 0094 // Drkonqi also has some python handling for some reason :shrug: 0095 QVERIFY(LinuxProc::isLibraryPath("/bin/a.py")); 0096 QVERIFY(LinuxProc::isLibraryPath("/bin/a.pyc")); 0097 QVERIFY(LinuxProc::isLibraryPath("/bin/a.py (deleted)")); 0098 } 0099 }; 0100 0101 QTEST_GUILESS_MAIN(LinuxProcMapsParserTest) 0102 0103 #include "linuxprocmapsparsertest.moc"