• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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