@@ -105,41 +105,56 @@ void middle_pgsql_t::table_desc::build_index(std::string const &conninfo) const
105105 db_connection.exec (m_create_fw_dep_indexes);
106106}
107107
108- namespace {
109- // Decodes a portion of an array literal from postgres */
110- // Argument should point to beginning of literal, on return points to delimiter */
111- inline char const *decode_upto (char const *src, char *dst)
108+ /* *
109+ * Decode item in an array literal from PostgreSQL to the next delimiter.
110+ *
111+ * \param src Pointer to the text with the array literal.
112+ * \param dst The decoded item is written to this string. The string is
113+ * cleared before use.
114+ * \returns Pointer to the delimiter found.
115+ * \throws runtime_error If the input string ends before the delimiter is found.
116+ */
117+ static char const *decode_to_delimiter (char const *src, std::string *dst)
112118{
119+ assert (src);
120+ dst->clear ();
121+
113122 bool const quoted = (*src == ' "' );
114123 if (quoted) {
115124 ++src;
116125 }
117126
118127 while (quoted ? (*src != ' "' ) : (*src != ' ,' && *src != ' }' )) {
128+ if (*src == ' \0 ' ) {
129+ throw std::runtime_error{
130+ " Parsing array literal from database failed." };
131+ }
119132 if (*src == ' \\ ' ) {
120133 switch (src[1 ]) {
121134 case ' n' :
122- * dst++ = ' \n ' ;
135+ dst-> append ( 1 , ' \n ' ) ;
123136 break ;
124137 case ' t' :
125- * dst++ = ' \t ' ;
138+ dst-> append ( 1 , ' \t ' ) ;
126139 break ;
127140 default :
128- * dst++ = src[1 ];
141+ dst-> append ( 1 , src[1 ]) ;
129142 break ;
130143 }
131144 src += 2 ;
132145 } else {
133- * dst++ = *src++;
146+ dst-> append ( 1 , *src++) ;
134147 }
135148 }
149+
136150 if (quoted) {
137151 ++src;
138152 }
139- *dst = 0 ;
153+
140154 return src;
141155}
142156
157+ namespace {
143158template <typename T>
144159void pgsql_parse_tags (char const *string, osmium::memory::Buffer *buffer,
145160 T *obuilder)
@@ -148,15 +163,15 @@ void pgsql_parse_tags(char const *string, osmium::memory::Buffer *buffer,
148163 return ;
149164 }
150165
151- char key[1024 ];
152- char val[1024 ];
153166 osmium::builder::TagListBuilder builder{*buffer, obuilder};
154167
168+ std::string key;
169+ std::string val;
155170 while (*string != ' }' ) {
156- string = decode_upto (string, key);
171+ string = decode_to_delimiter (string, & key);
157172 // String points to the comma */
158173 ++string;
159- string = decode_upto (string, val);
174+ string = decode_to_delimiter (string, & val);
160175 builder.add_tag (key, val);
161176 // String points to the comma or closing '}' */
162177 if (*string == ' ,' ) {
@@ -172,15 +187,15 @@ void pgsql_parse_members(char const *string, osmium::memory::Buffer *buffer,
172187 return ;
173188 }
174189
175- char role[ 1024 ] ;
190+ std::string role;
176191 osmium::builder::RelationMemberListBuilder builder{*buffer, obuilder};
177192
178193 while (*string != ' }' ) {
179194 char type = string[0 ];
180195 char *endp = nullptr ;
181196 osmid_t id = std::strtoll (string + 1 , &endp, 10 );
182197 // String points to the comma */
183- string = decode_upto (endp + 1 , role);
198+ string = decode_to_delimiter (endp + 1 , & role);
184199 builder.add_member (osmium::char_to_item_type (type), id, role);
185200 // String points to the comma or closing '}' */
186201 if (*string == ' ,' ) {
0 commit comments