Promote cns argument to int64_t to ensure correctness
Some operations such as cns(-1) would end up emitting the wrong thing, because the -1 literal would be interpreted as int32_t and only four bytes would get copied across by memcpy. The result is that cns(-1) would in fact emit the constant 4294967295 (= 2^32-1) which is bound to lead to wrong code. A former workaround involved using cns(-1LL). I removed this use case to show that this is now kosher (and added a test to show that nothing broke - use TRACE=hhir:2 to check).
Esse commit está contido em:
@@ -160,9 +160,25 @@ struct ConstData : IRExtraData {
|
||||
"Constant data was larger than supported");
|
||||
static_assert(std::is_pod<T>::value,
|
||||
"Constant data wasn't a pod?");
|
||||
std::memcpy(&m_dataBits, &data, sizeof data);
|
||||
const auto toCopy = promoteIfNeeded(data);
|
||||
std::memcpy(&m_dataBits, &toCopy, sizeof(toCopy));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct needsPromotion {
|
||||
static constexpr bool value = std::is_integral<T>::value ||
|
||||
std::is_same<T,bool>::value ||
|
||||
std::is_enum<T>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<needsPromotion<T>::value, int64_t>::type
|
||||
promoteIfNeeded(T t) { return t; }
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!needsPromotion<T>::value, T>::type
|
||||
promoteIfNeeded(T t) { return t; }
|
||||
|
||||
template<class T>
|
||||
T as() const {
|
||||
T ret;
|
||||
|
||||
@@ -3251,7 +3251,7 @@ void HhbcTranslator::emitMod() {
|
||||
SSATmp *res = m_tb->cond(
|
||||
curFunc(),
|
||||
[&] (Block* taken) {
|
||||
SSATmp* negone = gen(OpEq, tr, cns(-1LL));
|
||||
SSATmp* negone = gen(OpEq, tr, cns(-1));
|
||||
gen(JmpNZero, taken, negone);
|
||||
},
|
||||
[&] {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
function int_min() {
|
||||
return ~PHP_INT_MAX;
|
||||
}
|
||||
|
||||
function int_negone() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function main() {
|
||||
var_dump(int_min() % -1);
|
||||
var_dump(int_min() % int_negone());
|
||||
}
|
||||
main();
|
||||
@@ -0,0 +1,2 @@
|
||||
int(0)
|
||||
int(0)
|
||||
Referência em uma Nova Issue
Bloquear um usuário