1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <google/protobuf/pyext/unknown_field_set.h>
32
33 #define PY_SSIZE_T_CLEAN
34 #include <Python.h>
35
36 #include <memory>
37 #include <set>
38
39 #include <google/protobuf/message.h>
40 #include <google/protobuf/unknown_field_set.h>
41 #include <google/protobuf/wire_format_lite.h>
42 #include <google/protobuf/pyext/message.h>
43 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
44
45 namespace google {
46 namespace protobuf {
47 namespace python {
48
49 namespace unknown_field_set {
50
Len(PyObject * pself)51 static Py_ssize_t Len(PyObject* pself) {
52 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
53 if (self->fields == nullptr) {
54 PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
55 return -1;
56 }
57 return self->fields->field_count();
58 }
59
60 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index);
61
Item(PyObject * pself,Py_ssize_t index)62 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
63 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
64 if (self->fields == nullptr) {
65 PyErr_Format(PyExc_ValueError, "UnknownFieldSet does not exist. ");
66 return nullptr;
67 }
68 Py_ssize_t total_size = self->fields->field_count();
69 if (index < 0) {
70 index = total_size + index;
71 }
72 if (index < 0 || index >= total_size) {
73 PyErr_Format(PyExc_IndexError, "index (%zd) out of range", index);
74 return nullptr;
75 }
76 return unknown_field_set::NewPyUnknownField(self, index);
77 }
78
New(PyTypeObject * type,PyObject * args,PyObject * kwargs)79 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
80 if (args == nullptr || PyTuple_Size(args) != 1) {
81 PyErr_SetString(PyExc_TypeError,
82 "Must provide a message to create UnknownFieldSet");
83 return nullptr;
84 }
85
86 PyObject* c_message;
87 if (!PyArg_ParseTuple(args, "O", &c_message)) {
88 PyErr_SetString(PyExc_TypeError,
89 "Must provide a message to create UnknownFieldSet");
90 return nullptr;
91 }
92
93 if (!PyObject_TypeCheck(c_message, CMessage_Type)) {
94 PyErr_Format(PyExc_TypeError,
95 "Parameter to UnknownFieldSet() must be a message "
96 "got %s.",
97 Py_TYPE(c_message)->tp_name);
98 return nullptr;
99 }
100
101 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
102 PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
103 if (self == nullptr) {
104 return nullptr;
105 }
106
107 // Top UnknownFieldSet should set parent nullptr.
108 self->parent = nullptr;
109
110 // Copy c_message's UnknownFieldSet.
111 Message* message = reinterpret_cast<CMessage*>(c_message)->message;
112 const Reflection* reflection = message->GetReflection();
113 self->fields = new google::protobuf::UnknownFieldSet;
114 self->fields->MergeFrom(reflection->GetUnknownFields(*message));
115 return reinterpret_cast<PyObject*>(self);
116 }
117
NewPyUnknownField(PyUnknownFieldSet * parent,Py_ssize_t index)118 PyObject* NewPyUnknownField(PyUnknownFieldSet* parent, Py_ssize_t index) {
119 PyUnknownField* self = reinterpret_cast<PyUnknownField*>(
120 PyType_GenericAlloc(&PyUnknownField_Type, 0));
121 if (self == nullptr) {
122 return nullptr;
123 }
124
125 Py_INCREF(parent);
126 self->parent = parent;
127 self->index = index;
128
129 return reinterpret_cast<PyObject*>(self);
130 }
131
Dealloc(PyObject * pself)132 static void Dealloc(PyObject* pself) {
133 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(pself);
134 if (self->parent == nullptr) {
135 delete self->fields;
136 } else {
137 Py_CLEAR(self->parent);
138 }
139 auto* py_type = Py_TYPE(pself);
140 self->~PyUnknownFieldSet();
141 py_type->tp_free(pself);
142 }
143
144 static PySequenceMethods SqMethods = {
145 Len, /* sq_length */
146 nullptr, /* sq_concat */
147 nullptr, /* sq_repeat */
148 Item, /* sq_item */
149 nullptr, /* sq_slice */
150 nullptr, /* sq_ass_item */
151 };
152
153 } // namespace unknown_field_set
154
155 PyTypeObject PyUnknownFieldSet_Type = {
156 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
157 ".PyUnknownFieldSet", // tp_name
158 sizeof(PyUnknownFieldSet), // tp_basicsize
159 0, // tp_itemsize
160 unknown_field_set::Dealloc, // tp_dealloc
161 #if PY_VERSION_HEX < 0x03080000
162 nullptr, // tp_print
163 #else
164 0, // tp_vectorcall_offset
165 #endif
166 nullptr, // tp_getattr
167 nullptr, // tp_setattr
168 nullptr, // tp_compare
169 nullptr, // tp_repr
170 nullptr, // tp_as_number
171 &unknown_field_set::SqMethods, // tp_as_sequence
172 nullptr, // tp_as_mapping
173 PyObject_HashNotImplemented, // tp_hash
174 nullptr, // tp_call
175 nullptr, // tp_str
176 nullptr, // tp_getattro
177 nullptr, // tp_setattro
178 nullptr, // tp_as_buffer
179 Py_TPFLAGS_DEFAULT, // tp_flags
180 "unknown field set", // tp_doc
181 nullptr, // tp_traverse
182 nullptr, // tp_clear
183 nullptr, // tp_richcompare
184 0, // tp_weaklistoffset
185 nullptr, // tp_iter
186 nullptr, // tp_iternext
187 nullptr, // tp_methods
188 nullptr, // tp_members
189 nullptr, // tp_getset
190 nullptr, // tp_base
191 nullptr, // tp_dict
192 nullptr, // tp_descr_get
193 nullptr, // tp_descr_set
194 0, // tp_dictoffset
195 nullptr, // tp_init
196 nullptr, // tp_alloc
197 unknown_field_set::New, // tp_new
198 };
199
200 namespace unknown_field {
PyUnknownFieldSet_FromUnknownFieldSet(PyUnknownFieldSet * parent,const UnknownFieldSet & fields)201 static PyObject* PyUnknownFieldSet_FromUnknownFieldSet(
202 PyUnknownFieldSet* parent, const UnknownFieldSet& fields) {
203 PyUnknownFieldSet* self = reinterpret_cast<PyUnknownFieldSet*>(
204 PyType_GenericAlloc(&PyUnknownFieldSet_Type, 0));
205 if (self == nullptr) {
206 return nullptr;
207 }
208
209 Py_INCREF(parent);
210 self->parent = parent;
211 self->fields = const_cast<UnknownFieldSet*>(&fields);
212
213 return reinterpret_cast<PyObject*>(self);
214 }
215
GetUnknownField(PyUnknownField * self)216 const UnknownField* GetUnknownField(PyUnknownField* self) {
217 const UnknownFieldSet* fields = self->parent->fields;
218 if (fields == nullptr) {
219 PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
220 return nullptr;
221 }
222 Py_ssize_t total_size = fields->field_count();
223 if (self->index >= total_size) {
224 PyErr_Format(PyExc_ValueError, "UnknownField does not exist. ");
225 return nullptr;
226 }
227 return &fields->field(self->index);
228 }
229
GetFieldNumber(PyUnknownField * self,void * closure)230 static PyObject* GetFieldNumber(PyUnknownField* self, void* closure) {
231 const UnknownField* unknown_field = GetUnknownField(self);
232 if (unknown_field == nullptr) {
233 return nullptr;
234 }
235 return PyLong_FromLong(unknown_field->number());
236 }
237
238 using internal::WireFormatLite;
GetWireType(PyUnknownField * self,void * closure)239 static PyObject* GetWireType(PyUnknownField* self, void* closure) {
240 const UnknownField* unknown_field = GetUnknownField(self);
241 if (unknown_field == nullptr) {
242 return nullptr;
243 }
244
245 // Assign a default value to suppress may-uninitialized warnings (errors
246 // when built in some places).
247 WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT;
248 switch (unknown_field->type()) {
249 case UnknownField::TYPE_VARINT:
250 wire_type = WireFormatLite::WIRETYPE_VARINT;
251 break;
252 case UnknownField::TYPE_FIXED32:
253 wire_type = WireFormatLite::WIRETYPE_FIXED32;
254 break;
255 case UnknownField::TYPE_FIXED64:
256 wire_type = WireFormatLite::WIRETYPE_FIXED64;
257 break;
258 case UnknownField::TYPE_LENGTH_DELIMITED:
259 wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
260 break;
261 case UnknownField::TYPE_GROUP:
262 wire_type = WireFormatLite::WIRETYPE_START_GROUP;
263 break;
264 }
265 return PyLong_FromLong(wire_type);
266 }
267
GetData(PyUnknownField * self,void * closure)268 static PyObject* GetData(PyUnknownField* self, void* closure) {
269 const UnknownField* field = GetUnknownField(self);
270 if (field == nullptr) {
271 return nullptr;
272 }
273 PyObject* data = nullptr;
274 switch (field->type()) {
275 case UnknownField::TYPE_VARINT:
276 data = PyLong_FromUnsignedLongLong(field->varint());
277 break;
278 case UnknownField::TYPE_FIXED32:
279 data = PyLong_FromUnsignedLong(field->fixed32());
280 break;
281 case UnknownField::TYPE_FIXED64:
282 data = PyLong_FromUnsignedLongLong(field->fixed64());
283 break;
284 case UnknownField::TYPE_LENGTH_DELIMITED:
285 data = PyBytes_FromStringAndSize(field->length_delimited().data(),
286 field->GetLengthDelimitedSize());
287 break;
288 case UnknownField::TYPE_GROUP:
289 data =
290 PyUnknownFieldSet_FromUnknownFieldSet(self->parent, field->group());
291 break;
292 }
293 return data;
294 }
295
Dealloc(PyObject * pself)296 static void Dealloc(PyObject* pself) {
297 PyUnknownField* self = reinterpret_cast<PyUnknownField*>(pself);
298 Py_CLEAR(self->parent);
299 }
300
301 static PyGetSetDef Getters[] = {
302 {"field_number", (getter)GetFieldNumber, nullptr},
303 {"wire_type", (getter)GetWireType, nullptr},
304 {"data", (getter)GetData, nullptr},
305 {nullptr},
306 };
307
308 } // namespace unknown_field
309
310 PyTypeObject PyUnknownField_Type = {
311 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
312 ".PyUnknownField", // tp_name
313 sizeof(PyUnknownField), // tp_basicsize
314 0, // tp_itemsize
315 unknown_field::Dealloc, // tp_dealloc
316 #if PY_VERSION_HEX < 0x03080000
317 nullptr, // tp_print
318 #else
319 0, // tp_vectorcall_offset
320 #endif
321 nullptr, // tp_getattr
322 nullptr, // tp_setattr
323 nullptr, // tp_compare
324 nullptr, // tp_repr
325 nullptr, // tp_as_number
326 nullptr, // tp_as_sequence
327 nullptr, // tp_as_mapping
328 PyObject_HashNotImplemented, // tp_hash
329 nullptr, // tp_call
330 nullptr, // tp_str
331 nullptr, // tp_getattro
332 nullptr, // tp_setattro
333 nullptr, // tp_as_buffer
334 Py_TPFLAGS_DEFAULT, // tp_flags
335 "unknown field", // tp_doc
336 nullptr, // tp_traverse
337 nullptr, // tp_clear
338 nullptr, // tp_richcompare
339 0, // tp_weaklistoffset
340 nullptr, // tp_iter
341 nullptr, // tp_iternext
342 nullptr, // tp_methods
343 nullptr, // tp_members
344 unknown_field::Getters, // tp_getset
345 nullptr, // tp_base
346 nullptr, // tp_dict
347 nullptr, // tp_descr_get
348 nullptr, // tp_descr_set
349 0, // tp_dictoffset
350 nullptr, // tp_init
351 };
352
353 } // namespace python
354 } // namespace protobuf
355 } // namespace google
356