Skip to content

Commit 95416a9

Browse files
committed
Add null checks to get_field
1 parent c58621b commit 95416a9

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

php/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ext/google/protobuf/Makefile
2+
ext/google/protobuf/configure
3+
ext/google/protobuf/BUILD_STAMP
4+
ext/google/protobuf/wkt.inc
5+
ext/google/protobuf/*.dep
6+
ext/google/protobuf/*.cache
7+
ext/google/protobuf/*.h.in
8+
tmp/
9+

php/ext/google/protobuf/message.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ static zend_object* Message_create(zend_class_entry* class_type) {
6464
Message_SuppressDefaultProperties(class_type);
6565
zend_object_std_init(&intern->std, class_type);
6666
intern->std.handlers = &message_object_handlers;
67+
intern->desc = NULL;
68+
6769
Arena_Init(&intern->arena);
6870
return &intern->std;
6971
}
@@ -88,6 +90,56 @@ static void Message_dtor(zend_object* obj) {
8890
* Helper function to look up a field given a member name (as a string).
8991
*/
9092
static const upb_FieldDef* get_field(Message* msg, zend_string* member) {
93+
//fprintf(stderr, "get_field\n");
94+
95+
if (!msg || !msg->desc || !msg->desc->msgdef) {
96+
// zend_string* class_name = msg ? msg->std.ce->name : NULL;
97+
// zend_class_entry* parent_ce = msg && msg->std.ce->parent ? msg->std.ce->parent : NULL;
98+
99+
// fprintf(stderr,
100+
// "get_field: Invalid msg or desc: msg=%p, desc=%p\n",
101+
// (void*)msg, (void*)msg->desc
102+
// );
103+
104+
// if (class_name) {
105+
// fprintf(stderr, "Class name: %s\n", ZSTR_VAL(class_name));
106+
// } else {
107+
// fprintf(stderr, "Class name: (null)\n");
108+
// }
109+
110+
// if (parent_ce) {
111+
// fprintf(stderr, "Parent class: %s\n", ZSTR_VAL(parent_ce->name));
112+
// } else {
113+
// fprintf(stderr, "Parent class: (none)\n");
114+
// }
115+
116+
// // Print the full stack trace
117+
// fprintf(stderr, "Full stack trace:\n");
118+
// const zend_execute_data* frame = EG(current_execute_data);
119+
// while (frame) {
120+
// const zend_function* func = frame->func;
121+
// const char* function_name = func->common.function_name
122+
// ? ZSTR_VAL(func->common.function_name)
123+
// : "(unknown)";
124+
// const char* class_name = func->common.scope
125+
// ? ZSTR_VAL(func->common.scope->name)
126+
// : "(none)";
127+
// const char* filename = func->op_array.filename
128+
// ? ZSTR_VAL(func->op_array.filename)
129+
// : "(unknown)";
130+
// uint32_t line = frame->opline ? frame->opline->lineno : 0;
131+
132+
// fprintf(stderr, " at %s::%s() in %s on line %u\n",
133+
// class_name, function_name, filename, line);
134+
135+
// // Move to the previous frame
136+
// frame = frame->prev_execute_data;
137+
// }
138+
139+
zend_throw_exception_ex(NULL, 0, "Message is uninitialized or corrupted.");
140+
return NULL;
141+
}
142+
91143
const upb_MessageDef* m = msg->desc->msgdef;
92144
const upb_FieldDef* f = upb_MessageDef_FindFieldByNameWithSize(
93145
m, ZSTR_VAL(member), ZSTR_LEN(member));
@@ -345,6 +397,13 @@ static zval* Message_read_property(zend_object* obj, zend_string* member,
345397
*/
346398
static zval* Message_write_property(zend_object* obj, zend_string* member,
347399
zval* val, void** cache_slot) {
400+
// fprintf(
401+
// stderr,
402+
// "Message_write_property: obj->ce->name=%s, member=%s\n",
403+
// ZSTR_VAL(obj->ce->name),
404+
// ZSTR_VAL(member)
405+
// );
406+
348407
Message* intern = (Message*)obj;
349408
const upb_FieldDef* f = get_field(intern, member);
350409

php/tests/extends_test.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
require_once (dirname(__DIR__) . '/vendor/autoload.php');
4+
require_once (__DIR__ . '/test_util.php');
5+
6+
use Foo\TestMessage;
7+
8+
class TestMessageProxy extends TestMessage
9+
{
10+
private $foo;
11+
12+
public function __construct($data = NULL) {
13+
if (0 < func_num_args()) {
14+
parent::__construct($data);
15+
}
16+
}
17+
18+
public function setFoo($foo) {
19+
print("setFoo($foo)\n");
20+
$this->foo = $foo;
21+
}
22+
23+
public function getFoo() {
24+
print("getFoo()\n");
25+
26+
return $this->foo;
27+
//return 'bar';
28+
}
29+
}
30+
31+
$p = new TestMessageProxy();
32+
33+
try {
34+
$p->setFoo('bar');
35+
} catch (Exception $e) {
36+
print("TraceAsString: " . $e->getTraceAsString() . "\n");
37+
}
38+
39+
assert('bar' === $p->getFoo());

php/tests/optional_test.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
require_once (dirname(__DIR__) . '/vendor/autoload.php');
4+
require_once (__DIR__ . '/test_util.php');
5+
6+
use Foo\TestMessage;
7+
8+
$m = new TestMessage([]);
9+
10+
$m->setTrueOptionalString(null);
11+
12+
var_dump($m->getTrueOptionalString());

0 commit comments

Comments
 (0)