Skip to content

Commit 88ef4fd

Browse files
committed
Add support for Zval IS_INDIRECT
As mentioned in #219, I believe we're making incorrect use of IS_CALLABLE on Zval types right now. Zval type bits are never actually stored as IS_CALLABLE, which overlaps with the _actual_ type value of IS_INDIRECT. IS_INDIRECT is almost the same as IS_REFERENCE, but is a direct reference to another Zval rather than reference object. As `Zval::is_callable()` and `Zval::callable()` don't actually make use of `IS_CALLABLE` then I think it's safe to switch this out.
1 parent 87ac43d commit 88ef4fd

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

allowed_bindings.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ bind! {
121121
IS_CONSTANT_AST_EX,
122122
IS_DOUBLE,
123123
IS_FALSE,
124+
IS_INDIRECT,
124125
IS_INTERNED_STRING_EX,
125126
IS_LONG,
126127
IS_MIXED,
@@ -141,6 +142,7 @@ bind! {
141142
IS_PTR,
142143
MAY_BE_ANY,
143144
MAY_BE_BOOL,
145+
PHP_INI_PERDIR,
144146
USING_ZTS,
145147
ZEND_ACC_ABSTRACT,
146148
ZEND_ACC_ANON_CLASS,

docsrs_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub const IS_CONSTANT_AST: u32 = 11;
1919
pub const IS_CALLABLE: u32 = 12;
2020
pub const IS_VOID: u32 = 14;
2121
pub const IS_MIXED: u32 = 16;
22+
pub const IS_INDIRECT: u32 = 12;
2223
pub const IS_PTR: u32 = 13;
2324
pub const _IS_BOOL: u32 = 18;
2425
pub const Z_TYPE_FLAGS_SHIFT: u32 = 8;

src/flags.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use bitflags::bitflags;
66
use crate::ffi::ZEND_ACC_REUSE_GET_ITERATOR;
77
use crate::ffi::{
88
CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, IS_ARRAY, IS_CALLABLE,
9-
IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR,
10-
IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED,
9+
IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_INDIRECT, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT,
10+
IS_PTR, IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED,
1111
IS_UNDEF, IS_VOID, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE,
1212
ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR,
1313
ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE,
@@ -185,6 +185,7 @@ pub enum DataType {
185185
Mixed,
186186
Bool,
187187
Ptr,
188+
Indirect,
188189
}
189190

190191
impl Default for DataType {
@@ -208,6 +209,7 @@ impl DataType {
208209
DataType::Object(_) => IS_OBJECT,
209210
DataType::Resource => IS_RESOURCE,
210211
DataType::Reference => IS_RESOURCE,
212+
DataType::Indirect => IS_INDIRECT,
211213
DataType::Callable => IS_CALLABLE,
212214
DataType::ConstantExpression => IS_CONSTANT_AST,
213215
DataType::Void => IS_VOID,
@@ -275,7 +277,7 @@ impl From<u32> for DataType {
275277
}
276278

277279
contains!(IS_VOID, Void);
278-
contains!(IS_CALLABLE, Callable);
280+
contains!(IS_INDIRECT, Indirect);
279281
contains!(IS_CONSTANT_AST, ConstantExpression);
280282
contains!(IS_REFERENCE, Reference);
281283
contains!(IS_RESOURCE, Resource);
@@ -318,6 +320,7 @@ impl Display for DataType {
318320
DataType::Bool => write!(f, "Bool"),
319321
DataType::Mixed => write!(f, "Mixed"),
320322
DataType::Ptr => write!(f, "Pointer"),
323+
DataType::Indirect => write!(f, "Indirect"),
321324
}
322325
}
323326
}
@@ -327,9 +330,9 @@ mod tests {
327330
use super::DataType;
328331
use crate::ffi::{
329332
IS_ARRAY, IS_ARRAY_EX, IS_CALLABLE, IS_CONSTANT_AST, IS_CONSTANT_AST_EX, IS_DOUBLE,
330-
IS_FALSE, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX, IS_REFERENCE,
331-
IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, IS_STRING_EX, IS_TRUE, IS_UNDEF,
332-
IS_VOID,
333+
IS_FALSE, IS_INDIRECT, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX,
334+
IS_REFERENCE, IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, IS_STRING_EX,
335+
IS_TRUE, IS_UNDEF, IS_VOID,
333336
};
334337
use std::convert::TryFrom;
335338

@@ -353,7 +356,7 @@ mod tests {
353356
test!(IS_RESOURCE, Resource);
354357
test!(IS_REFERENCE, Reference);
355358
test!(IS_CONSTANT_AST, ConstantExpression);
356-
test!(IS_CALLABLE, Callable);
359+
test!(IS_INDIRECT, Indirect);
357360
test!(IS_VOID, Void);
358361

359362
test!(IS_INTERNED_STRING_EX, String);

src/types/zval.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,24 @@ impl Zval {
206206
}
207207
}
208208

209+
/// Returns the value of the zval if it is an internal indirect reference.
210+
pub fn indirect(&self) -> Option<&Zval> {
211+
if self.is_indirect() {
212+
Some(unsafe { &*(self.value.zv as *mut Zval) })
213+
} else {
214+
None
215+
}
216+
}
217+
218+
/// Returns a mutable reference to the zval if it is an internal indirect reference.
219+
pub fn indirect_mut(&self) -> Option<&mut Zval> {
220+
if self.is_indirect() {
221+
Some(unsafe { &mut *(self.value.zv as *mut Zval) })
222+
} else {
223+
None
224+
}
225+
}
226+
209227
/// Returns the value of the zval if it is a reference.
210228
pub fn reference(&self) -> Option<&Zval> {
211229
if self.is_reference() {
@@ -321,6 +339,11 @@ impl Zval {
321339
self.get_type() == DataType::Reference
322340
}
323341

342+
/// Returns true if the zval is a reference, false otherwise.
343+
pub fn is_indirect(&self) -> bool {
344+
self.get_type() == DataType::Indirect
345+
}
346+
324347
/// Returns true if the zval is callable, false otherwise.
325348
pub fn is_callable(&self) -> bool {
326349
let ptr: *const Self = self;
@@ -593,6 +616,7 @@ impl Debug for Zval {
593616
DataType::ConstantExpression => field!(Option::<()>::None),
594617
DataType::Void => field!(Option::<()>::None),
595618
DataType::Bool => field!(self.bool()),
619+
DataType::Indirect => field!(self.indirect()),
596620
// SAFETY: We are not accessing the pointer.
597621
DataType::Ptr => field!(unsafe { self.ptr::<c_void>() }),
598622
};

0 commit comments

Comments
 (0)