mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 04:36:07 +00:00
[clang][bytecode] Check memove/memcpy for available elements (#121383)
Both destination and source pointer need to have at least as many elements as requested.
This commit is contained in:
parent
b35d3453dd
commit
f0d60170cc
@ -17,6 +17,7 @@
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/TargetBuiltins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/SipHash.h"
|
||||
|
||||
namespace clang {
|
||||
@ -1837,6 +1838,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
|
||||
assert(Call->getNumArgs() == 3);
|
||||
unsigned ID = Func->getBuiltinID();
|
||||
Pointer DestPtr = getParam<Pointer>(Frame, 0);
|
||||
const ASTContext &ASTCtx = S.getASTContext();
|
||||
const Pointer &SrcPtr = getParam<Pointer>(Frame, 1);
|
||||
const APSInt &Size =
|
||||
peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)));
|
||||
@ -1857,34 +1859,55 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
|
||||
Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
|
||||
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
|
||||
<< /*IsMove=*/Move << /*IsWchar=*/false << !SrcPtr.isZero()
|
||||
<< DiagPtr.toDiagnosticString(S.getASTContext());
|
||||
<< DiagPtr.toDiagnosticString(ASTCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
QualType ElemType;
|
||||
if (DestPtr.getFieldDesc()->isArray())
|
||||
ElemType = DestPtr.getFieldDesc()->getElemQualType();
|
||||
else
|
||||
ElemType = DestPtr.getType();
|
||||
QualType DestElemType;
|
||||
size_t RemainingDestElems;
|
||||
if (DestPtr.getFieldDesc()->isArray()) {
|
||||
DestElemType = DestPtr.getFieldDesc()->getElemQualType();
|
||||
RemainingDestElems = (DestPtr.getNumElems() - DestPtr.getIndex());
|
||||
} else {
|
||||
DestElemType = DestPtr.getType();
|
||||
RemainingDestElems = 1;
|
||||
}
|
||||
unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
|
||||
|
||||
unsigned ElemSize =
|
||||
S.getASTContext().getTypeSizeInChars(ElemType).getQuantity();
|
||||
if (Size.urem(ElemSize) != 0) {
|
||||
if (Size.urem(DestElemSize) != 0) {
|
||||
S.FFDiag(S.Current->getSource(OpPC),
|
||||
diag::note_constexpr_memcpy_unsupported)
|
||||
<< Move << /*IsWchar=*/false << 0 << ElemType << Size << ElemSize;
|
||||
<< Move << /*IsWchar=*/false << 0 << DestElemType << Size
|
||||
<< DestElemSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
QualType SrcElemType;
|
||||
if (SrcPtr.getFieldDesc()->isArray())
|
||||
size_t RemainingSrcElems;
|
||||
if (SrcPtr.getFieldDesc()->isArray()) {
|
||||
SrcElemType = SrcPtr.getFieldDesc()->getElemQualType();
|
||||
else
|
||||
RemainingSrcElems = (SrcPtr.getNumElems() - SrcPtr.getIndex());
|
||||
} else {
|
||||
SrcElemType = SrcPtr.getType();
|
||||
RemainingSrcElems = 1;
|
||||
}
|
||||
unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
|
||||
|
||||
if (!S.getASTContext().hasSameUnqualifiedType(ElemType, SrcElemType)) {
|
||||
if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
|
||||
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
|
||||
<< Move << SrcElemType << ElemType;
|
||||
<< Move << SrcElemType << DestElemType;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough elements to read from and write to/
|
||||
size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
|
||||
size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
|
||||
if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {
|
||||
APInt N = Size.udiv(DestElemSize);
|
||||
S.FFDiag(S.Current->getSource(OpPC),
|
||||
diag::note_constexpr_memcpy_unsupported)
|
||||
<< Move << /*IsWChar*/ false << (Size.ugt(RemainingSrcBytes) ? 1 : 2)
|
||||
<< DestElemType << toString(N, 10, /*Signed=*/false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1905,7 +1928,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
|
||||
// As a last resort, reject dummy pointers.
|
||||
if (DestPtr.isDummy() || SrcPtr.isDummy())
|
||||
return false;
|
||||
assert(Size.getZExtValue() % ElemSize == 0);
|
||||
assert(Size.getZExtValue() % DestElemSize == 0);
|
||||
if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
|
||||
return false;
|
||||
|
||||
|
@ -1244,6 +1244,15 @@ namespace BuiltinMemcpy {
|
||||
}
|
||||
static_assert(cpyptr());
|
||||
|
||||
#ifndef __AVR__
|
||||
constexpr int test_memmove(int a, int b, int n) {
|
||||
int arr[4] = {1, 2, 3, 4};
|
||||
__builtin_memmove(arr + a, arr + b, n); // both-note {{destination is not a contiguous array of at least 3 elements of type 'int'}}
|
||||
return result(arr);
|
||||
}
|
||||
static_assert(test_memmove(2, 0, 12) == 4234); // both-error {{constant}} \
|
||||
// both-note {{in call}}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace Memcmp {
|
||||
|
Loading…
x
Reference in New Issue
Block a user