1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Google LLC nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "upb/reflection/message.h"
29 
30 #include <string.h>
31 
32 #include "upb/collections/map.h"
33 #include "upb/hash/common.h"
34 #include "upb/message/accessors.h"
35 #include "upb/message/message.h"
36 #include "upb/mini_table/field_internal.h"
37 #include "upb/reflection/def.h"
38 #include "upb/reflection/def_pool.h"
39 #include "upb/reflection/def_type.h"
40 #include "upb/reflection/field_def_internal.h"
41 #include "upb/reflection/message_def.h"
42 #include "upb/reflection/oneof_def.h"
43 
44 // Must be last.
45 #include "upb/port/def.inc"
46 
upb_Message_HasFieldByDef(const upb_Message * msg,const upb_FieldDef * f)47 bool upb_Message_HasFieldByDef(const upb_Message* msg, const upb_FieldDef* f) {
48   UPB_ASSERT(upb_FieldDef_HasPresence(f));
49   return upb_Message_HasField(msg, upb_FieldDef_MiniTable(f));
50 }
51 
upb_Message_WhichOneof(const upb_Message * msg,const upb_OneofDef * o)52 const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg,
53                                            const upb_OneofDef* o) {
54   const upb_FieldDef* f = upb_OneofDef_Field(o, 0);
55   if (upb_OneofDef_IsSynthetic(o)) {
56     UPB_ASSERT(upb_OneofDef_FieldCount(o) == 1);
57     return upb_Message_HasFieldByDef(msg, f) ? f : NULL;
58   } else {
59     const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
60     uint32_t oneof_case = upb_Message_WhichOneofFieldNumber(msg, field);
61     f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
62     UPB_ASSERT((f != NULL) == (oneof_case != 0));
63     return f;
64   }
65 }
66 
upb_Message_GetFieldByDef(const upb_Message * msg,const upb_FieldDef * f)67 upb_MessageValue upb_Message_GetFieldByDef(const upb_Message* msg,
68                                            const upb_FieldDef* f) {
69   upb_MessageValue default_val = upb_FieldDef_Default(f);
70   upb_MessageValue ret;
71   _upb_Message_GetField(msg, upb_FieldDef_MiniTable(f), &default_val, &ret);
72   return ret;
73 }
74 
upb_Message_Mutable(upb_Message * msg,const upb_FieldDef * f,upb_Arena * a)75 upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
76                                             const upb_FieldDef* f,
77                                             upb_Arena* a) {
78   UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
79   if (upb_FieldDef_HasPresence(f) && !upb_Message_HasFieldByDef(msg, f)) {
80     // We need to skip the upb_Message_GetFieldByDef() call in this case.
81     goto make;
82   }
83 
84   upb_MessageValue val = upb_Message_GetFieldByDef(msg, f);
85   if (val.array_val) {
86     return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
87   }
88 
89   upb_MutableMessageValue ret;
90 make:
91   if (!a) return (upb_MutableMessageValue){.array = NULL};
92   if (upb_FieldDef_IsMap(f)) {
93     const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
94     const upb_FieldDef* key =
95         upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
96     const upb_FieldDef* value =
97         upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
98     ret.map =
99         upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
100   } else if (upb_FieldDef_IsRepeated(f)) {
101     ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
102   } else {
103     UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
104     const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
105     ret.msg = upb_Message_New(upb_MessageDef_MiniTable(m), a);
106   }
107 
108   val.array_val = ret.array;
109   upb_Message_SetFieldByDef(msg, f, val, a);
110 
111   return ret;
112 }
113 
upb_Message_SetFieldByDef(upb_Message * msg,const upb_FieldDef * f,upb_MessageValue val,upb_Arena * a)114 bool upb_Message_SetFieldByDef(upb_Message* msg, const upb_FieldDef* f,
115                                upb_MessageValue val, upb_Arena* a) {
116   return _upb_Message_SetField(msg, upb_FieldDef_MiniTable(f), &val, a);
117 }
118 
upb_Message_ClearFieldByDef(upb_Message * msg,const upb_FieldDef * f)119 void upb_Message_ClearFieldByDef(upb_Message* msg, const upb_FieldDef* f) {
120   upb_Message_ClearField(msg, upb_FieldDef_MiniTable(f));
121 }
122 
upb_Message_ClearByDef(upb_Message * msg,const upb_MessageDef * m)123 void upb_Message_ClearByDef(upb_Message* msg, const upb_MessageDef* m) {
124   _upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
125 }
126 
upb_Message_Next(const upb_Message * msg,const upb_MessageDef * m,const upb_DefPool * ext_pool,const upb_FieldDef ** out_f,upb_MessageValue * out_val,size_t * iter)127 bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
128                       const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
129                       upb_MessageValue* out_val, size_t* iter) {
130   size_t i = *iter;
131   size_t n = upb_MessageDef_FieldCount(m);
132   UPB_UNUSED(ext_pool);
133 
134   // Iterate over normal fields, returning the first one that is set.
135   while (++i < n) {
136     const upb_FieldDef* f = upb_MessageDef_Field(m, i);
137     const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
138     upb_MessageValue val = upb_Message_GetFieldByDef(msg, f);
139 
140     // Skip field if unset or empty.
141     if (upb_MiniTableField_HasPresence(field)) {
142       if (!upb_Message_HasFieldByDef(msg, f)) continue;
143     } else {
144       switch (upb_FieldMode_Get(field)) {
145         case kUpb_FieldMode_Map:
146           if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
147           break;
148         case kUpb_FieldMode_Array:
149           if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
150           break;
151         case kUpb_FieldMode_Scalar:
152           if (!_upb_MiniTable_ValueIsNonZero(&val, field)) continue;
153           break;
154       }
155     }
156 
157     *out_val = val;
158     *out_f = f;
159     *iter = i;
160     return true;
161   }
162 
163   if (ext_pool) {
164     // Return any extensions that are set.
165     size_t count;
166     const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
167     if (i - n < count) {
168       ext += count - 1 - (i - n);
169       memcpy(out_val, &ext->data, sizeof(*out_val));
170       *out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
171       *iter = i;
172       return true;
173     }
174   }
175 
176   *iter = i;
177   return false;
178 }
179 
_upb_Message_DiscardUnknown(upb_Message * msg,const upb_MessageDef * m,int depth)180 bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
181                                  int depth) {
182   size_t iter = kUpb_Message_Begin;
183   const upb_FieldDef* f;
184   upb_MessageValue val;
185   bool ret = true;
186 
187   if (--depth == 0) return false;
188 
189   _upb_Message_DiscardUnknown_shallow(msg);
190 
191   while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
192     const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
193     if (!subm) continue;
194     if (upb_FieldDef_IsMap(f)) {
195       const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
196       const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
197       upb_Map* map = (upb_Map*)val.map_val;
198       size_t iter = kUpb_Map_Begin;
199 
200       if (!val_m) continue;
201 
202       upb_MessageValue map_key, map_val;
203       while (upb_Map_Next(map, &map_key, &map_val, &iter)) {
204         if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
205                                          depth)) {
206           ret = false;
207         }
208       }
209     } else if (upb_FieldDef_IsRepeated(f)) {
210       const upb_Array* arr = val.array_val;
211       size_t i, n = upb_Array_Size(arr);
212       for (i = 0; i < n; i++) {
213         upb_MessageValue elem = upb_Array_Get(arr, i);
214         if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
215                                          depth)) {
216           ret = false;
217         }
218       }
219     } else {
220       if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
221                                        depth)) {
222         ret = false;
223       }
224     }
225   }
226 
227   return ret;
228 }
229 
upb_Message_DiscardUnknown(upb_Message * msg,const upb_MessageDef * m,int maxdepth)230 bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
231                                 int maxdepth) {
232   return _upb_Message_DiscardUnknown(msg, m, maxdepth);
233 }
234