Skip to content

Commit 0c47feb

Browse files
committed
[clang] Fix out-of-bounds memory access in ComputeLineNumbers
Differential Revision: https://reviews.llvm.org/D72409 # Conflicts: # clang/unittests/Basic/SourceManagerTest.cpp
1 parent 4f65b63 commit 0c47feb

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

clang/lib/Basic/SourceManager.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,23 +1250,18 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
12501250

12511251
const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
12521252
const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
1253+
const std::size_t BufLen = End - Buf;
12531254
unsigned I = 0;
1254-
while (true) {
1255-
// Skip over the contents of the line.
1256-
while (Buf[I] != '\n' && Buf[I] != '\r' && Buf[I] != '\0')
1257-
++I;
1258-
1259-
if (Buf[I] == '\n' || Buf[I] == '\r') {
1255+
while (I < BufLen) {
1256+
if (Buf[I] == '\n') {
1257+
LineOffsets.push_back(I + 1);
1258+
} else if (Buf[I] == '\r') {
12601259
// If this is \r\n, skip both characters.
1261-
if (Buf[I] == '\r' && Buf[I+1] == '\n')
1260+
if (I + 1 < BufLen && Buf[I + 1] == '\n')
12621261
++I;
1263-
++I;
1264-
LineOffsets.push_back(I);
1265-
} else {
1266-
// Otherwise, this is a NUL. If end of file, exit.
1267-
if (Buf+I == End) break;
1268-
++I;
1262+
LineOffsets.push_back(I + 1);
12691263
}
1264+
++I;
12701265
}
12711266

12721267
// Copy the offsets into the FileInfo structure.

clang/unittests/Basic/SourceManagerTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include "clang/Lex/PreprocessorOptions.h"
2121
#include "llvm/ADT/SmallString.h"
2222
#include "llvm/Config/llvm-config.h"
23+
#include "llvm/Support/Process.h"
2324
#include "gtest/gtest.h"
25+
#include <cstddef>
2426

2527
using namespace clang;
2628

@@ -241,6 +243,28 @@ TEST_F(SourceManagerTest, getInvalidBOM) {
241243
"UTF-32 (LE)");
242244
}
243245

246+
// Regression test - there was an out of bound access for buffers not terminated by zero.
247+
TEST_F(SourceManagerTest, getLineNumber) {
248+
const unsigned pageSize = llvm::sys::Process::getPageSizeEstimate();
249+
std::unique_ptr<char[]> source(new char[pageSize]);
250+
for(unsigned i = 0; i < pageSize; ++i) {
251+
source[i] = 'a';
252+
}
253+
254+
std::unique_ptr<llvm::MemoryBuffer> Buf =
255+
llvm::MemoryBuffer::getMemBuffer(
256+
llvm::MemoryBufferRef(
257+
llvm::StringRef(source.get(), 3), "whatever"
258+
),
259+
false
260+
);
261+
262+
FileID mainFileID = SourceMgr.createFileID(std::move(Buf));
263+
SourceMgr.setMainFileID(mainFileID);
264+
265+
ASSERT_NO_FATAL_FAILURE(SourceMgr.getLineNumber(mainFileID, 1, nullptr));
266+
}
267+
244268
#if defined(LLVM_ON_UNIX)
245269

246270
TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {

0 commit comments

Comments
 (0)