Files
archived-llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h
Zachary Turner d947f15959 Fix use after free in BinaryStream library.
This was reported by the ASAN bot, and it turned out to be
a fairly fundamental problem with the design of VarStreamArray
and the way it passes context information to the extractor.

The fix was cumbersome, and I'm not entirely pleased with it,
so I plan to revisit this design in the future when I'm not
pressed to get the bots green again.  For now, this fixes
the issue by storing the context information by value instead
of by reference, and introduces some impossibly-confusing
template magic to make things "work".

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301999 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-03 05:34:00 +00:00

81 lines
2.4 KiB
C++

//===- ModuleDebugFragment.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
class ModuleDebugFragment;
// Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
struct ModuleDebugFragmentHeader {
support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum
support::ulittle32_t Length; // number of bytes occupied by this record.
};
class ModuleDebugFragmentRecord {
public:
ModuleDebugFragmentRecord();
ModuleDebugFragmentRecord(ModuleDebugFragmentKind Kind, BinaryStreamRef Data);
static Error initialize(BinaryStreamRef Stream,
ModuleDebugFragmentRecord &Info);
uint32_t getRecordLength() const;
ModuleDebugFragmentKind kind() const;
BinaryStreamRef getRecordData() const;
private:
ModuleDebugFragmentKind Kind;
BinaryStreamRef Data;
};
class ModuleDebugFragmentRecordBuilder {
public:
ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind,
ModuleDebugFragment &Frag);
uint32_t calculateSerializedLength();
Error commit(BinaryStreamWriter &Writer);
private:
ModuleDebugFragmentKind Kind;
ModuleDebugFragment &Frag;
};
} // namespace codeview
template <>
struct VarStreamArrayExtractor<codeview::ModuleDebugFragmentRecord> {
typedef void ContextType;
static Error extract(BinaryStreamRef Stream, uint32_t &Length,
codeview::ModuleDebugFragmentRecord &Info) {
if (auto EC = codeview::ModuleDebugFragmentRecord::initialize(Stream, Info))
return EC;
Length = Info.getRecordLength();
return Error::success();
}
};
namespace codeview {
typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray;
}
} // namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H