------------------------------------------------------------------------
r243945 | chandlerc | 2015-08-03 20:52:52 -0700 (Mon, 03 Aug 2015) | 5 lines
[UB] Fix two cases of UB in copy/pasted code from SmallVector.
We should really stop copying and pasting code around. =/
Found by UBSan.
------------------------------------------------------------------------
------------------------------------------------------------------------
r243946 | chandlerc | 2015-08-03 20:52:56 -0700 (Mon, 03 Aug 2015) | 9 lines
[UB] Fix the two ways that we would try to memcpy from a null buffer in
the nested name specifier code.
First, skip the entire thing when the input is empty.
Next, handle the case where we started off with a null buffer and a zero
capacity to skip copying and freeing.
This was found with UBSan.
------------------------------------------------------------------------
------------------------------------------------------------------------
r243947 | chandlerc | 2015-08-03 20:52:58 -0700 (Mon, 03 Aug 2015) | 4 lines
[UB] When attaching empty strings to the AST, use an empty StringRef
rather than forcing the bump pointer allocator to produce a viable
pointer. This also fixes UB when we would try to memcpy from the null
incoming StringRef.
------------------------------------------------------------------------
------------------------------------------------------------------------
r243948 | chandlerc | 2015-08-03 20:53:00 -0700 (Mon, 03 Aug 2015) | 9 lines
[UB] Another place where we were trying to put string data into
a BumpPtrAllocator. This at least now handles the case where there is no
concatentation without calling memcpy on a null pointer. It might be
interesting to handle the case where everything is empty without
round-tripping through the allocator, but it wasn't clear to me if the
pointer returned is significant in any way, so I've left it in
a conservatively more-correct state.
Again, found with UBSan.
------------------------------------------------------------------------
------------------------------------------------------------------------
r243949 | chandlerc | 2015-08-03 20:53:01 -0700 (Mon, 03 Aug 2015) | 4 lines
[UB] Guard two calls to memcpy in generated attribute code to handle
null StringRef objects as inputs.
Found by UBSan.
------------------------------------------------------------------------
------------------------------------------------------------------------
r243950 | chandlerc | 2015-08-03 20:53:04 -0700 (Mon, 03 Aug 2015) | 8 lines
[UB] Avoid a really broken call to realloc that would later result in
a bad call to memcpy.
When we only have a buffer from one of the two reparse calls, we can
just return that buffer rather than going through the realloc/memcpy
dance.
Found with UBsan.
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_37@244223
91177308-0d34-0410-b5e6-
96231b3b80d8
T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
// Copy the elements over.
- if (std::is_class<T>::value) {
- std::uninitialized_copy(Begin, End, NewElts);
- // Destroy the original elements.
- destroy_range(Begin, End);
- }
- else {
- // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
- memcpy(NewElts, Begin, CurSize * sizeof(T));
+ if (Begin != End) {
+ if (std::is_class<T>::value) {
+ std::uninitialized_copy(Begin, End, NewElts);
+ // Destroy the original elements.
+ destroy_range(Begin, End);
+ } else {
+ // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
+ memcpy(NewElts, Begin, CurSize * sizeof(T));
+ }
}
// ASTContext never frees any memory.
T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
// Copy the elements over.
- if (std::is_class<T>::value) {
- std::uninitialized_copy(Begin, End, NewElts);
- // Destroy the original elements.
- destroy_range(Begin, End);
- }
- else {
- // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
- memcpy(NewElts, Begin, CurSize * sizeof(T));
+ if (Begin != End) {
+ if (std::is_class<T>::value) {
+ std::uninitialized_copy(Begin, End, NewElts);
+ // Destroy the original elements.
+ destroy_range(Begin, End);
+ } else {
+ // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
+ memcpy(NewElts, Begin, CurSize * sizeof(T));
+ }
}
// For now, leak 'Begin'. We can add it back to a freelist in
namespace {
void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
unsigned &BufferCapacity) {
+ if (Start == End)
+ return;
+
if (BufferSize + (End - Start) > BufferCapacity) {
// Reallocate the buffer.
- unsigned NewCapacity
- = std::max((unsigned)(BufferCapacity? BufferCapacity * 2
- : sizeof(void*) * 2),
- (unsigned)(BufferSize + (End - Start)));
+ unsigned NewCapacity = std::max(
+ (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
+ (unsigned)(BufferSize + (End - Start)));
char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
- memcpy(NewBuffer, Buffer, BufferSize);
-
- if (BufferCapacity)
+ if (BufferCapacity) {
+ memcpy(NewBuffer, Buffer, BufferSize);
free(Buffer);
+ }
Buffer = NewBuffer;
BufferCapacity = NewCapacity;
}
}
static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
+ if (str.empty())
+ return StringRef();
size_t size = str.size();
char *buffer = new (C) char[size];
memcpy(buffer, str.data(), size);
/// are concatenated.
StringRef internString(StringRef A, StringRef B = StringRef()) {
char *Data = DebugInfoNames.Allocate<char>(A.size() + B.size());
- std::memcpy(Data, A.data(), A.size());
- std::memcpy(Data + A.size(), B.data(), B.size());
+ if (!A.empty())
+ std::memcpy(Data, A.data(), A.size());
+ if (!B.empty())
+ std::memcpy(Data + A.size(), B.data(), B.size());
return StringRef(Data, A.size() + B.size());
}
};
if (ret)
return ret;
+ if (num_unsaved_files_no_try_idx == 0) {
+ *unsaved_files = unsaved_files_try_idx;
+ *num_unsaved_files = num_unsaved_files_try_idx;
+ return 0;
+ }
+ if (num_unsaved_files_try_idx == 0) {
+ *unsaved_files = unsaved_files_no_try_idx;
+ *num_unsaved_files = num_unsaved_files_no_try_idx;
+ return 0;
+ }
+
*num_unsaved_files = num_unsaved_files_no_try_idx + num_unsaved_files_try_idx;
*unsaved_files
= (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx,
OS << " " << getLowerName() << "Length = S.size();\n";
OS << " this->" << getLowerName() << " = new (C, 1) char ["
<< getLowerName() << "Length];\n";
- OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
+ OS << " if (!S.empty())\n";
+ OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
<< getLowerName() << "Length);\n";
OS << " }";
}
OS << "A->get" << getUpperName() << "()";
}
void writeCtorBody(raw_ostream &OS) const override {
- OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
+ OS << " if (!" << getUpperName() << ".empty())\n";
+ OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
<< ".data(), " << getLowerName() << "Length);";
}
void writeCtorInitializers(raw_ostream &OS) const override {