@@ -62,7 +62,15 @@ void irep_serializationt::reference_convert(
6262 else
6363 {
6464 read_irep (in, irep);
65- insert_on_read (id, irep);
65+
66+ if (id >= ireps_container.ireps_on_read .size ())
67+ ireps_container.ireps_on_read .resize (1 + id * 2 , {false , get_nil_irep ()});
68+
69+ // guard against self-referencing ireps
70+ if (ireps_container.ireps_on_read [id].first )
71+ throw deserialization_exceptiont (" irep id read twice." );
72+
73+ ireps_container.ireps_on_read [id] = {true , irep};
6674 }
6775}
6876
@@ -100,72 +108,29 @@ void irep_serializationt::read_irep(
100108 }
101109}
102110
111+ // / Serialize an irept
112+ // / \param irep: source irept to serialize
113+ // / \param out: target output stream
103114void irep_serializationt::reference_convert (
104115 const irept &irep,
105116 std::ostream &out)
106117{
107118 std::size_t h=ireps_container.irep_full_hash_container .number (irep);
108119
109- // should be merged with insert
110- ireps_containert::ireps_on_writet::const_iterator fi=
111- ireps_container.ireps_on_write .find (h);
120+ const auto res = ireps_container.ireps_on_write .insert (
121+ {h, ireps_container.ireps_on_write .size ()});
112122
113- if (fi==ireps_container.ireps_on_write .end ())
114- {
115- size_t id=insert_on_write (h);
116- write_gb_word (out, id);
123+ write_gb_word (out, res.first ->second );
124+ if (res.second )
117125 write_irep (out, irep);
118- }
119- else
120- {
121- write_gb_word (out, fi->second );
122- }
123- }
124-
125- // / inserts an irep into the hashtable
126- // / \par parameters: a size_t and an irep
127- // / \return true on success, false otherwise
128- std::size_t irep_serializationt::insert_on_write (std::size_t h)
129- {
130- std::pair<ireps_containert::ireps_on_writet::const_iterator, bool > res=
131- ireps_container.ireps_on_write .insert (
132- std::make_pair (h, ireps_container.ireps_on_write .size ()));
133-
134- if (!res.second )
135- return ireps_container.ireps_on_write .size ();
136- else
137- return res.first ->second ;
138126}
139127
140- // / inserts an irep into the hashtable, but only the id-hashtable (only to be
141- // / used upon reading ireps from a file)
142- // / \par parameters: a size_t and an irep
143- // / \return true on success, false otherwise
144- std::size_t irep_serializationt::insert_on_read (
145- std::size_t id,
146- const irept &i)
147- {
148- if (id>=ireps_container.ireps_on_read .size ())
149- ireps_container.ireps_on_read .resize (1 +id*2 ,
150- std::pair<bool , irept>(false , get_nil_irep ()));
151-
152- if (ireps_container.ireps_on_read [id].first )
153- throw deserialization_exceptiont (" irep id read twice." );
154- else
155- {
156- ireps_container.ireps_on_read [id]=
157- std::pair<bool , irept>(true , i);
158- }
159-
160- return id;
161- }
162-
163- // / outputs 4 characters for a long, most-significant byte first
164- // / \par parameters: an output stream and a number
165- // / \return nothing
128+ // / Write 7 bits of `u` each time, least-significant byte first, until we have
129+ // / zero.
130+ // / \param out: target stream
131+ // / \param u: number to write
166132void write_gb_word (std::ostream &out, std::size_t u)
167133{
168- // we write 7 bits each time, until we have zero
169134
170135 while (true )
171136 {
@@ -182,9 +147,9 @@ void write_gb_word(std::ostream &out, std::size_t u)
182147 }
183148}
184149
185- // / reads 4 characters and builds a long int from them
186- // / \par parameters: a stream
187- // / \return a long
150+ // / Interpret a stream of byte as a 7-bit encoded unsigned number.
151+ // / \param in: input stream
152+ // / \return decoded number
188153std::size_t irep_serializationt::read_gb_word (std::istream &in)
189154{
190155 std::size_t res=0 ;
@@ -193,19 +158,25 @@ std::size_t irep_serializationt::read_gb_word(std::istream &in)
193158
194159 while (in.good ())
195160 {
161+ if (shift_distance >= sizeof (res) * 8 )
162+ throw deserialization_exceptiont (" input number too large" );
163+
196164 unsigned char ch=static_cast <unsigned char >(in.get ());
197165 res|=(size_t (ch&0x7f ))<<shift_distance;
198166 shift_distance+=7 ;
199167 if ((ch&0x80 )==0 )
200168 break ;
201169 }
202170
171+ if (!in.good ())
172+ throw deserialization_exceptiont (" unexpected end of input stream" );
173+
203174 return res;
204175}
205176
206177// / outputs the string and then a zero byte.
207- // / \par parameters: an output stream and a string
208- // / \return nothing
178+ // / \param out: output stream
179+ // / \param s: string to output
209180void write_gb_string (std::ostream &out, const std::string &s)
210181{
211182 for (std::string::const_iterator it=s.begin ();
@@ -221,7 +192,7 @@ void write_gb_string(std::ostream &out, const std::string &s)
221192}
222193
223194// / reads a string from the stream
224- // / \par parameters: a stream
195+ // / \param in: input stream
225196// / \return a string
226197irep_idt irep_serializationt::read_gb_string (std::istream &in)
227198{
@@ -244,9 +215,9 @@ irep_idt irep_serializationt::read_gb_string(std::istream &in)
244215 return irep_idt (std::string (read_buffer.data (), length));
245216}
246217
247- // / outputs the string reference
248- // / \par parameters: an output stream and a string
249- // / \return nothing
218+ // / Output a string and maintain a reference to it
219+ // / \param out: output stream
220+ // / \param s: string to output
250221void irep_serializationt::write_string_ref (
251222 std::ostream &out,
252223 const irep_idt &s)
@@ -265,8 +236,8 @@ void irep_serializationt::write_string_ref(
265236 }
266237}
267238
268- // / reads a string reference from the stream
269- // / \par parameters: a stream
239+ // / Read a string reference from the stream
240+ // / \param in: input stream
270241// / \return a string
271242irep_idt irep_serializationt::read_string_ref (std::istream &in)
272243{
@@ -276,15 +247,12 @@ irep_idt irep_serializationt::read_string_ref(std::istream &in)
276247 ireps_container.string_rev_map .resize (1 +id*2 ,
277248 std::pair<bool , irep_idt>(false , irep_idt ()));
278249
279- if (ireps_container.string_rev_map [id].first )
280- {
281- return ireps_container.string_rev_map [id].second ;
282- }
283- else
250+ if (!ireps_container.string_rev_map [id].first )
284251 {
285252 irep_idt s=read_gb_string (in);
286253 ireps_container.string_rev_map [id]=
287254 std::pair<bool , irep_idt>(true , s);
288- return ireps_container.string_rev_map [id].second ;
289255 }
256+
257+ return ireps_container.string_rev_map [id].second ;
290258}
0 commit comments