95.78% Lines (159/166) 100.00% Functions (10/10)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #include "src/rfc/detail/rules.hpp" 10   #include "src/rfc/detail/rules.hpp"
11   11  
12   #include <boost/http/error.hpp> 12   #include <boost/http/error.hpp>
13   #include <boost/http/detail/config.hpp> 13   #include <boost/http/detail/config.hpp>
14   #include <boost/http/rfc/token_rule.hpp> 14   #include <boost/http/rfc/token_rule.hpp>
15   15  
16   #include <boost/core/detail/string_view.hpp> 16   #include <boost/core/detail/string_view.hpp>
17   #include <boost/url/grammar/delim_rule.hpp> 17   #include <boost/url/grammar/delim_rule.hpp>
18   #include <boost/url/grammar/digit_chars.hpp> 18   #include <boost/url/grammar/digit_chars.hpp>
19   #include <boost/url/grammar/error.hpp> 19   #include <boost/url/grammar/error.hpp>
20   #include <boost/url/grammar/hexdig_chars.hpp> 20   #include <boost/url/grammar/hexdig_chars.hpp>
21   #include <boost/url/grammar/lut_chars.hpp> 21   #include <boost/url/grammar/lut_chars.hpp>
22   #include <boost/url/grammar/parse.hpp> 22   #include <boost/url/grammar/parse.hpp>
23   #include <boost/url/grammar/tuple_rule.hpp> 23   #include <boost/url/grammar/tuple_rule.hpp>
24   24  
25   #include "src/rfc/detail/rules.hpp" 25   #include "src/rfc/detail/rules.hpp"
26   26  
27   namespace boost { 27   namespace boost {
28   namespace http { 28   namespace http {
29   namespace detail { 29   namespace detail {
30   30  
31   auto 31   auto
HITCBC 32   28890 crlf_rule_t:: 32   28890 crlf_rule_t::
33   parse( 33   parse(
34   char const*& it, 34   char const*& it,
35   char const* end) const noexcept -> 35   char const* end) const noexcept ->
36   system::result<value_type> 36   system::result<value_type>
37   { 37   {
HITCBC 38   28890 if(it == end) 38   28890 if(it == end)
HITCBC 39   6535 return grammar::error::need_more; 39   6535 return grammar::error::need_more;
HITCBC 40   22355 if(*it != '\r') 40   22355 if(*it != '\r')
HITCBC 41   29 return grammar::error::mismatch; 41   29 return grammar::error::mismatch;
HITCBC 42   22326 ++it; 42   22326 ++it;
HITCBC 43   22326 if(it == end) 43   22326 if(it == end)
HITCBC 44   961 return grammar::error::need_more; 44   961 return grammar::error::need_more;
HITCBC 45   21365 if(*it != '\n') 45   21365 if(*it != '\n')
HITCBC 46   51 return grammar::error::mismatch; 46   51 return grammar::error::mismatch;
HITCBC 47   21314 ++it; 47   21314 ++it;
HITCBC 48   21314 return {}; 48   21314 return {};
49   } 49   }
50   50  
51   //------------------------------------------------ 51   //------------------------------------------------
52   52  
53   auto 53   auto
HITCBC 54   28506 version_rule_t:: 54   28506 version_rule_t::
55   parse( 55   parse(
56   char const*& it, 56   char const*& it,
57   char const* end) const noexcept -> 57   char const* end) const noexcept ->
58   system::result<value_type> 58   system::result<value_type>
59   { 59   {
HITCBC 60   28506 value_type v = 0; 60   28506 value_type v = 0;
HITCBC 61   28506 if(it == end) 61   28506 if(it == end)
62   { 62   {
63   // expected "HTTP/" 63   // expected "HTTP/"
HITCBC 64 - 1619 return grammar::error::need_more; 64 + 1619 BOOST_HTTP_RETURN_EC(
  65 + grammar::error::need_more);
65   } 66   }
HITCBC 66   26887 if(end - it >= 5) 67   26887 if(end - it >= 5)
67   { 68   {
HITCBC 68   22177 if(std::memcmp( 69   22177 if(std::memcmp(
69   it, "HTTP/", 5) != 0) 70   it, "HTTP/", 5) != 0)
70   { 71   {
MISUBC 71 - ✗ return grammar::error::mismatch; 72 + ✗ BOOST_HTTP_RETURN_EC(
  73 + grammar::error::mismatch);
72   } 74   }
HITCBC 73   22177 it += 5; 75   22177 it += 5;
74   } 76   }
HITCBC 75   26887 if(it == end) 77   26887 if(it == end)
76   { 78   {
77   // expected DIGIT 79   // expected DIGIT
HITCBC 78 - 1087 return grammar::error::need_more; 80 + 1087 BOOST_HTTP_RETURN_EC(
  81 + grammar::error::need_more);
79   } 82   }
HITCBC 80   25800 if(! grammar::digit_chars(*it)) 83   25800 if(! grammar::digit_chars(*it))
81   { 84   {
82   // expected DIGIT 85   // expected DIGIT
HITCBC 83 - 4710 return grammar::error::need_more; 86 + 4710 BOOST_HTTP_RETURN_EC(
  87 + grammar::error::need_more);
84   } 88   }
HITCBC 85   21090 v = 10 * (*it++ - '0'); 89   21090 v = 10 * (*it++ - '0');
HITCBC 86   21090 if(it == end) 90   21090 if(it == end)
87   { 91   {
88   // expected "." 92   // expected "."
HITCBC 89 - 1213 return grammar::error::need_more; 93 + 1213 BOOST_HTTP_RETURN_EC(
  94 + grammar::error::need_more);
90   } 95   }
HITCBC 91   19877 if(*it != '.') 96   19877 if(*it != '.')
92   { 97   {
93   // expected "." 98   // expected "."
MISUBC 94 - ✗ return grammar::error::need_more; 99 + ✗ BOOST_HTTP_RETURN_EC(
  100 + grammar::error::need_more);
95   } 101   }
HITCBC 96   19877 ++it; 102   19877 ++it;
HITCBC 97   19877 if(it == end) 103   19877 if(it == end)
98   { 104   {
99   // expected DIGIT 105   // expected DIGIT
HITCBC 100 - 1051 return grammar::error::need_more; 106 + 1051 BOOST_HTTP_RETURN_EC(
  107 + grammar::error::need_more);
101   } 108   }
HITCBC 102   18826 if(! grammar::digit_chars(*it)) 109   18826 if(! grammar::digit_chars(*it))
103   { 110   {
104   // expected DIGIT 111   // expected DIGIT
MISUBC 105 - ✗ return grammar::error::need_more; 112 + ✗ BOOST_HTTP_RETURN_EC(
  113 + grammar::error::need_more);
106   } 114   }
HITCBC 107   18826 v += *it++ - '0'; 115   18826 v += *it++ - '0';
HITCBC 108   18826 return v; 116   18826 return v;
109   } 117   }
110   118  
111   //------------------------------------------------ 119   //------------------------------------------------
112   120  
113   auto 121   auto
HITCBC 114   8184 status_code_rule_t:: 122   8184 status_code_rule_t::
115   parse( 123   parse(
116   char const*& it, 124   char const*& it,
117   char const* end) const noexcept -> 125   char const* end) const noexcept ->
118   system::result<value_type> 126   system::result<value_type>
119   { 127   {
120   auto const dig = 128   auto const dig =
HITCBC 121   19020 [](char c) -> int 129   19020 [](char c) -> int
122   { 130   {
HITCBC 123   19020 unsigned char uc(c - '0'); 131   19020 unsigned char uc(c - '0');
HITCBC 124   19020 if(uc > 9) 132   19020 if(uc > 9)
MISUBC 125   ✗ return -1; 133   ✗ return -1;
HITCBC 126   19020 return uc; 134   19020 return uc;
127   }; 135   };
128   136  
HITCBC 129   8184 if(it == end) 137   8184 if(it == end)
130   { 138   {
131   // end 139   // end
HITCBC 132 - 934 return grammar::error::need_more; 140 + 934 BOOST_HTTP_RETURN_EC(
  141 + grammar::error::need_more);
133   } 142   }
HITCBC 134   7250 auto it0 = it; 143   7250 auto it0 = it;
HITCBC 135   7250 int v = dig(*it); 144   7250 int v = dig(*it);
HITCBC 136   7250 if(v == -1) 145   7250 if(v == -1)
137   { 146   {
138   // expected DIGIT 147   // expected DIGIT
MISUBC 139 - ✗ return grammar::error::mismatch; 148 + ✗ BOOST_HTTP_RETURN_EC(
  149 + grammar::error::mismatch);
140   } 150   }
HITCBC 141   7250 value_type t; 151   7250 value_type t;
HITCBC 142   7250 t.v = 100 * v; 152   7250 t.v = 100 * v;
HITCBC 143   7250 ++it; 153   7250 ++it;
HITCBC 144   7250 if(it == end) 154   7250 if(it == end)
145   { 155   {
146   // end 156   // end
HITCBC 147 - 916 return grammar::error::need_more; 157 + 916 BOOST_HTTP_RETURN_EC(
  158 + grammar::error::need_more);
148   } 159   }
HITCBC 149   6334 v = dig(*it); 160   6334 v = dig(*it);
HITCBC 150   6334 if(v == -1) 161   6334 if(v == -1)
151   { 162   {
152   // expected DIGIT 163   // expected DIGIT
MISUBC 153 - ✗ return grammar::error::mismatch; 164 + ✗ BOOST_HTTP_RETURN_EC(
  165 + grammar::error::mismatch);
154   } 166   }
HITCBC 155   6334 t.v = t.v + (10 * v); 167   6334 t.v = t.v + (10 * v);
HITCBC 156   6334 ++it; 168   6334 ++it;
HITCBC 157   6334 if(it == end) 169   6334 if(it == end)
158   { 170   {
159   // end 171   // end
HITCBC 160 - 898 return grammar::error::need_more; 172 + 898 BOOST_HTTP_RETURN_EC(
  173 + grammar::error::need_more);
161   } 174   }
HITCBC 162   5436 v = dig(*it); 175   5436 v = dig(*it);
HITCBC 163   5436 if(v == -1) 176   5436 if(v == -1)
164   { 177   {
165   // expected DIGIT 178   // expected DIGIT
MISUBC 166 - ✗ return grammar::error::need_more; 179 + ✗ BOOST_HTTP_RETURN_EC(
  180 + grammar::error::need_more);
167   } 181   }
HITCBC 168   5436 t.v = t.v + v; 182   5436 t.v = t.v + v;
HITCBC 169   5436 ++it; 183   5436 ++it;
170   184  
HITCBC 171   5436 t.s = core::string_view(it0, it - it0); 185   5436 t.s = core::string_view(it0, it - it0);
HITCBC 172   5436 t.st = int_to_status(t.v); 186   5436 t.st = int_to_status(t.v);
HITCBC 173   5436 return t; 187   5436 return t;
174   } 188   }
175   189  
176   //------------------------------------------------ 190   //------------------------------------------------
177   191  
178   auto 192   auto
HITCBC 179   4556 reason_phrase_rule_t:: 193   4556 reason_phrase_rule_t::
180   parse( 194   parse(
181   char const*& it, 195   char const*& it,
182   char const* end) const noexcept -> 196   char const* end) const noexcept ->
183   system::result<value_type> 197   system::result<value_type>
184   { 198   {
HITCBC 185   4556 auto begin = it; 199   4556 auto begin = it;
HITCBC 186   4556 it = grammar::find_if_not(it, end, ws_vchars); 200   4556 it = grammar::find_if_not(it, end, ws_vchars);
HITCBC 187   4556 return core::string_view(begin, it); 201   4556 return core::string_view(begin, it);
188   } 202   }
189   203  
190   //------------------------------------------------ 204   //------------------------------------------------
191   205  
192   auto 206   auto
HITCBC 193   26365 field_name_rule_t:: 207   26365 field_name_rule_t::
194   parse( 208   parse(
195   char const*& it, 209   char const*& it,
196   char const* end) const noexcept -> 210   char const* end) const noexcept ->
197   system::result<value_type> 211   system::result<value_type>
198   { 212   {
HITCBC 199   26365 if( it == end ) 213   26365 if( it == end )
HITCBC 200 - 1 return grammar::error::need_more; 214 + 1 BOOST_HTTP_RETURN_EC(
  215 + grammar::error::need_more);
201   216  
HITCBC 202   26364 value_type v; 217   26364 value_type v;
203   218  
HITCBC 204   26364 auto begin = it; 219   26364 auto begin = it;
HITCBC 205   26364 auto rv = grammar::parse( 220   26364 auto rv = grammar::parse(
206   it, end, token_rule); 221   it, end, token_rule);
HITCBC 207   26364 if( rv.has_error() || (it != end) ) 222   26364 if( rv.has_error() || (it != end) )
208   { 223   {
HITCBC 209   15941 if( it != begin ) 224   15941 if( it != begin )
210   { 225   {
HITCBC 211   15875 v = core::string_view(begin, it - begin); 226   15875 v = core::string_view(begin, it - begin);
HITCBC 212   15875 return v; 227   15875 return v;
213   } 228   }
HITCBC 214 - 132 return make_error_code( 229 + 66 return error::bad_field_name;
DCB 215 - 66 error::bad_field_name);  
216   } 230   }
217   231  
HITCBC 218   10423 v = core::string_view(begin, end - begin); 232   10423 v = core::string_view(begin, end - begin);
HITCBC 219   10423 return v; 233   10423 return v;
220   } 234   }
221   235  
222   auto 236   auto
HITCBC 223   16144 field_value_rule_t:: 237   16144 field_value_rule_t::
224   parse( 238   parse(
225   char const*& it, 239   char const*& it,
226   char const* end) const noexcept -> 240   char const* end) const noexcept ->
227   system::result<value_type> 241   system::result<value_type>
228   { 242   {
HITCBC 229   16144 value_type v; 243   16144 value_type v;
HITCBC 230   16144 if( it == end ) 244   16144 if( it == end )
231   { 245   {
HITCBC 232   693 v.value = core::string_view(it, 0); 246   693 v.value = core::string_view(it, 0);
HITCBC 233   693 return v; 247   693 return v;
234   } 248   }
235   249  
236   // field-line = field-name ":" OWS field-value OWS 250   // field-line = field-name ":" OWS field-value OWS
237   // field-value = *field-content 251   // field-value = *field-content
238   // field-content = field-vchar 252   // field-content = field-vchar
239   // [ 1*( SP / HTAB / field-vchar ) field-vchar ] 253   // [ 1*( SP / HTAB / field-vchar ) field-vchar ]
240   // field-vchar = VCHAR / obs-text 254   // field-vchar = VCHAR / obs-text
241   // obs-text = %x80-FF 255   // obs-text = %x80-FF
242   // VCHAR = %x21-7E 256   // VCHAR = %x21-7E
243   // ; visible (printing) characters 257   // ; visible (printing) characters
244   258  
HITCBC 245   66585 auto is_field_vchar = [](unsigned char ch) 259   66585 auto is_field_vchar = [](unsigned char ch)
246   { 260   {
HITCBC 247   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80; 261   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80;
248   }; 262   };
249   263  
HITCBC 250   15451 char const* s0 = nullptr; 264   15451 char const* s0 = nullptr;
HITCBC 251   15451 char const* s1 = nullptr; 265   15451 char const* s1 = nullptr;
252   266  
HITCBC 253   15451 bool has_crlf = false; 267   15451 bool has_crlf = false;
HITCBC 254   15451 bool has_obs_fold = false; 268   15451 bool has_obs_fold = false;
255   269  
HITCBC 256   100095 while( it < end ) 270   100095 while( it < end )
257   { 271   {
HITCBC 258   96599 auto ch = *it; 272   96599 auto ch = *it;
HITCBC 259   96599 if( ws(ch) ) 273   96599 if( ws(ch) )
260   { 274   {
HITCBC 261   17363 ++it; 275   17363 ++it;
HITCBC 262   17363 continue; 276   17363 continue;
263   } 277   }
264   278  
HITCBC 265   79236 if( ch == '\r' ) 279   79236 if( ch == '\r' )
266   { 280   {
267   // too short to know if we have a potential obs-fold 281   // too short to know if we have a potential obs-fold
268   // occurrence 282   // occurrence
HITCBC 269   12651 if( end - it < 2 ) 283   12651 if( end - it < 2 )
HITCBC 270 - 592 return grammar::error::need_more; 284 + 592 BOOST_HTTP_RETURN_EC(
  285 + grammar::error::need_more);
271   286  
HITCBC 272   12059 if( it[1] != '\n' ) 287   12059 if( it[1] != '\n' )
HITCBC 273   53 goto done; 288   53 goto done;
274   289  
HITCBC 275   12006 if( end - it < 3 ) 290   12006 if( end - it < 3 )
HITCBC 276 - 546 return grammar::error::need_more; 291 + 546 BOOST_HTTP_RETURN_EC(
  292 + grammar::error::need_more);
277   293  
HITCBC 278   11460 if(! ws(it[2]) ) 294   11460 if(! ws(it[2]) )
279   { 295   {
HITCBC 280   10730 has_crlf = true; 296   10730 has_crlf = true;
HITCBC 281   10730 goto done; 297   10730 goto done;
282   } 298   }
283   299  
HITCBC 284   730 has_obs_fold = true; 300   730 has_obs_fold = true;
HITCBC 285   730 it = it + 3; 301   730 it = it + 3;
HITCBC 286   730 continue; 302   730 continue;
HITGIC 287   } 303   730 }
288   304  
HITCBC 289   66585 if(! is_field_vchar(ch) ) 305   66585 if(! is_field_vchar(ch) )
290   { 306   {
HITCBC 291   34 goto done; 307   34 goto done;
292   } 308   }
293   309  
HITCBC 294   66551 if(! s0 ) 310   66551 if(! s0 )
HITCBC 295   14348 s0 = it; 311   14348 s0 = it;
296   312  
HITCBC 297   66551 ++it; 313   66551 ++it;
HITCBC 298   66551 s1 = it; 314   66551 s1 = it;
299   } 315   }
300   316  
HITCBC 301   3496 done: 317   3496 done:
302   // later routines wind up doing pointer 318   // later routines wind up doing pointer
303   // subtraction using the .data() member 319   // subtraction using the .data() member
304   // of the value so we need a valid 0-len range 320   // of the value so we need a valid 0-len range
HITCBC 305   14313 if(! s0 ) 321   14313 if(! s0 )
306   { 322   {
HITCBC 307   939 s0 = it; 323   939 s0 = it;
HITCBC 308   939 s1 = s0; 324   939 s1 = s0;
309   } 325   }
310   326  
HITCBC 311   14313 v.value = core::string_view(s0, s1 - s0); 327   14313 v.value = core::string_view(s0, s1 - s0);
HITCBC 312   14313 v.has_crlf = has_crlf; 328   14313 v.has_crlf = has_crlf;
HITCBC 313   14313 v.has_obs_fold = has_obs_fold; 329   14313 v.has_obs_fold = has_obs_fold;
HITCBC 314   14313 return v; 330   14313 return v;
315   } 331   }
316   332  
317   auto 333   auto
HITCBC 318   37744 field_rule_t:: 334   37744 field_rule_t::
319   parse( 335   parse(
320   char const*& it, 336   char const*& it,
321   char const* end) const noexcept -> 337   char const* end) const noexcept ->
322   system::result<value_type> 338   system::result<value_type>
323   { 339   {
HITCBC 324   37744 if(it == end) 340   37744 if(it == end)
325   { 341   {
HITCBC 326 - 979 return grammar::error::need_more; 342 + 979 BOOST_HTTP_RETURN_EC(
  343 + grammar::error::need_more);
327   } 344   }
328   // check for leading CRLF 345   // check for leading CRLF
HITCBC 329   36765 if(it[0] == '\r') 346   36765 if(it[0] == '\r')
330   { 347   {
HITCBC 331   10641 ++it; 348   10641 ++it;
HITCBC 332   10641 if(it == end) 349   10641 if(it == end)
333   { 350   {
HITCBC 334 - 489 return grammar::error::need_more; 351 + 489 BOOST_HTTP_RETURN_EC(
  352 + grammar::error::need_more);
335   } 353   }
HITCBC 336   10152 if(*it != '\n') 354   10152 if(*it != '\n')
337   { 355   {
HITCBC 338 - 21 return grammar::error::mismatch; 356 + 21 BOOST_HTTP_RETURN_EC(
  357 + grammar::error::mismatch);
339   } 358   }
340   // end of fields 359   // end of fields
HITCBC 341   10131 ++it; 360   10131 ++it;
HITCBC 342 - 10131 return grammar::error::end_of_range; 361 + 10131 BOOST_HTTP_RETURN_EC(
  362 + grammar::error::end_of_range);
343   } 363   }
344   364  
HITCBC 345   26124 value_type v; 365   26124 value_type v;
346   auto rv = grammar::parse( 366   auto rv = grammar::parse(
HITCBC 347   26124 it, end, grammar::tuple_rule( 367   26124 it, end, grammar::tuple_rule(
348   field_name_rule, 368   field_name_rule,
HITCBC 349   26124 grammar::delim_rule(':'), 369   26124 grammar::delim_rule(':'),
350   field_value_rule, 370   field_value_rule,
HITCBC 351   26124 crlf_rule)); 371   26124 crlf_rule));
352   372  
HITCBC 353   26124 if( rv.has_error() ) 373   26124 if( rv.has_error() )
HITCBC 354   15410 return rv.error(); 374   15410 return rv.error();
355   375  
HITCBC 356   10714 auto val = rv.value(); 376   10714 auto val = rv.value();
HITCBC 357   10714 v.name = std::get<0>(val); 377   10714 v.name = std::get<0>(val);
HITCBC 358   10714 v.value = std::get<2>(val).value; 378   10714 v.value = std::get<2>(val).value;
HITCBC 359   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold; 379   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold;
360   380  
HITCBC 361   10714 return v; 381   10714 return v;
362   } 382   }
363   383  
364   //------------------------------------------------ 384   //------------------------------------------------
365   385  
366   void 386   void
HITCBC 367   244 remove_obs_fold( 387   244 remove_obs_fold(
368   char* it, 388   char* it,
369   char const* const end) noexcept 389   char const* const end) noexcept
370   { 390   {
HITCBC 371   2262 while(it != end) 391   2262 while(it != end)
372   { 392   {
HITCBC 373   2236 if(*it != '\r') 393   2236 if(*it != '\r')
374   { 394   {
HITCBC 375   1637 ++it; 395   1637 ++it;
HITCBC 376   1637 continue; 396   1637 continue;
377   } 397   }
HITCBC 378   599 if(end - it < 3) 398   599 if(end - it < 3)
HITCBC 379   218 break; 399   218 break;
HITCBC 380   381 BOOST_ASSERT(it[1] == '\n'); 400   381 BOOST_ASSERT(it[1] == '\n');
HITCBC 381   762 if( it[1] == '\n' && 401   762 if( it[1] == '\n' &&
HITCBC 382   381 ws(it[2])) 402   381 ws(it[2]))
383   { 403   {
HITCBC 384   378 it[0] = ' '; 404   378 it[0] = ' ';
HITCBC 385   378 it[1] = ' '; 405   378 it[1] = ' ';
HITCBC 386   378 it += 3; 406   378 it += 3;
387   } 407   }
388   else 408   else
389   { 409   {
HITCBC 390   3 ++it; 410   3 ++it;
391   } 411   }
392   } 412   }
HITCBC 393   244 } 413   244 }
394   414  
395   } // detail 415   } // detail
396   } // http 416   } // http
397   } // boost 417   } // boost