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 return grammar::error::need_more;
65   } 65   }
HITCBC 66   26887 if(end - it >= 5) 66   26887 if(end - it >= 5)
67   { 67   {
HITCBC 68   22177 if(std::memcmp( 68   22177 if(std::memcmp(
69   it, "HTTP/", 5) != 0) 69   it, "HTTP/", 5) != 0)
70   { 70   {
MISUBC 71   return grammar::error::mismatch; 71   return grammar::error::mismatch;
72   } 72   }
HITCBC 73   22177 it += 5; 73   22177 it += 5;
74   } 74   }
HITCBC 75   26887 if(it == end) 75   26887 if(it == end)
76   { 76   {
77   // expected DIGIT 77   // expected DIGIT
HITCBC 78   1087 return grammar::error::need_more; 78   1087 return grammar::error::need_more;
79   } 79   }
HITCBC 80   25800 if(! grammar::digit_chars(*it)) 80   25800 if(! grammar::digit_chars(*it))
81   { 81   {
82   // expected DIGIT 82   // expected DIGIT
HITCBC 83   4710 return grammar::error::need_more; 83   4710 return grammar::error::need_more;
84   } 84   }
HITCBC 85   21090 v = 10 * (*it++ - '0'); 85   21090 v = 10 * (*it++ - '0');
HITCBC 86   21090 if(it == end) 86   21090 if(it == end)
87   { 87   {
88   // expected "." 88   // expected "."
HITCBC 89   1213 return grammar::error::need_more; 89   1213 return grammar::error::need_more;
90   } 90   }
HITCBC 91   19877 if(*it != '.') 91   19877 if(*it != '.')
92   { 92   {
93   // expected "." 93   // expected "."
MISUBC 94   return grammar::error::need_more; 94   return grammar::error::need_more;
95   } 95   }
HITCBC 96   19877 ++it; 96   19877 ++it;
HITCBC 97   19877 if(it == end) 97   19877 if(it == end)
98   { 98   {
99   // expected DIGIT 99   // expected DIGIT
HITCBC 100   1051 return grammar::error::need_more; 100   1051 return grammar::error::need_more;
101   } 101   }
HITCBC 102   18826 if(! grammar::digit_chars(*it)) 102   18826 if(! grammar::digit_chars(*it))
103   { 103   {
104   // expected DIGIT 104   // expected DIGIT
MISUBC 105   return grammar::error::need_more; 105   return grammar::error::need_more;
106   } 106   }
HITCBC 107   18826 v += *it++ - '0'; 107   18826 v += *it++ - '0';
HITCBC 108   18826 return v; 108   18826 return v;
109   } 109   }
110   110  
111   //------------------------------------------------ 111   //------------------------------------------------
112   112  
113   auto 113   auto
HITCBC 114   8184 status_code_rule_t:: 114   8184 status_code_rule_t::
115   parse( 115   parse(
116   char const*& it, 116   char const*& it,
117   char const* end) const noexcept -> 117   char const* end) const noexcept ->
118   system::result<value_type> 118   system::result<value_type>
119   { 119   {
120   auto const dig = 120   auto const dig =
HITCBC 121   19020 [](char c) -> int 121   19020 [](char c) -> int
122   { 122   {
HITCBC 123   19020 unsigned char uc(c - '0'); 123   19020 unsigned char uc(c - '0');
HITCBC 124   19020 if(uc > 9) 124   19020 if(uc > 9)
MISUBC 125   return -1; 125   return -1;
HITCBC 126   19020 return uc; 126   19020 return uc;
127   }; 127   };
128   128  
HITCBC 129   8184 if(it == end) 129   8184 if(it == end)
130   { 130   {
131   // end 131   // end
HITCBC 132   934 return grammar::error::need_more; 132   934 return grammar::error::need_more;
133   } 133   }
HITCBC 134   7250 auto it0 = it; 134   7250 auto it0 = it;
HITCBC 135   7250 int v = dig(*it); 135   7250 int v = dig(*it);
HITCBC 136   7250 if(v == -1) 136   7250 if(v == -1)
137   { 137   {
138   // expected DIGIT 138   // expected DIGIT
MISUBC 139   return grammar::error::mismatch; 139   return grammar::error::mismatch;
140   } 140   }
HITCBC 141   7250 value_type t; 141   7250 value_type t;
HITCBC 142   7250 t.v = 100 * v; 142   7250 t.v = 100 * v;
HITCBC 143   7250 ++it; 143   7250 ++it;
HITCBC 144   7250 if(it == end) 144   7250 if(it == end)
145   { 145   {
146   // end 146   // end
HITCBC 147   916 return grammar::error::need_more; 147   916 return grammar::error::need_more;
148   } 148   }
HITCBC 149   6334 v = dig(*it); 149   6334 v = dig(*it);
HITCBC 150   6334 if(v == -1) 150   6334 if(v == -1)
151   { 151   {
152   // expected DIGIT 152   // expected DIGIT
MISUBC 153   return grammar::error::mismatch; 153   return grammar::error::mismatch;
154   } 154   }
HITCBC 155   6334 t.v = t.v + (10 * v); 155   6334 t.v = t.v + (10 * v);
HITCBC 156   6334 ++it; 156   6334 ++it;
HITCBC 157   6334 if(it == end) 157   6334 if(it == end)
158   { 158   {
159   // end 159   // end
HITCBC 160   898 return grammar::error::need_more; 160   898 return grammar::error::need_more;
161   } 161   }
HITCBC 162   5436 v = dig(*it); 162   5436 v = dig(*it);
HITCBC 163   5436 if(v == -1) 163   5436 if(v == -1)
164   { 164   {
165   // expected DIGIT 165   // expected DIGIT
MISUBC 166   return grammar::error::need_more; 166   return grammar::error::need_more;
167   } 167   }
HITCBC 168   5436 t.v = t.v + v; 168   5436 t.v = t.v + v;
HITCBC 169   5436 ++it; 169   5436 ++it;
170   170  
HITCBC 171   5436 t.s = core::string_view(it0, it - it0); 171   5436 t.s = core::string_view(it0, it - it0);
HITCBC 172   5436 t.st = int_to_status(t.v); 172   5436 t.st = int_to_status(t.v);
HITCBC 173   5436 return t; 173   5436 return t;
174   } 174   }
175   175  
176   //------------------------------------------------ 176   //------------------------------------------------
177   177  
178   auto 178   auto
HITCBC 179   4556 reason_phrase_rule_t:: 179   4556 reason_phrase_rule_t::
180   parse( 180   parse(
181   char const*& it, 181   char const*& it,
182   char const* end) const noexcept -> 182   char const* end) const noexcept ->
183   system::result<value_type> 183   system::result<value_type>
184   { 184   {
HITCBC 185   4556 auto begin = it; 185   4556 auto begin = it;
HITCBC 186   4556 it = grammar::find_if_not(it, end, ws_vchars); 186   4556 it = grammar::find_if_not(it, end, ws_vchars);
HITCBC 187   4556 return core::string_view(begin, it); 187   4556 return core::string_view(begin, it);
188   } 188   }
189   189  
190   //------------------------------------------------ 190   //------------------------------------------------
191   191  
192   auto 192   auto
HITCBC 193   26365 field_name_rule_t:: 193   26365 field_name_rule_t::
194   parse( 194   parse(
195   char const*& it, 195   char const*& it,
196   char const* end) const noexcept -> 196   char const* end) const noexcept ->
197   system::result<value_type> 197   system::result<value_type>
198   { 198   {
HITCBC 199   26365 if( it == end ) 199   26365 if( it == end )
HITCBC 200   1 return grammar::error::need_more; 200   1 return grammar::error::need_more;
201   201  
HITCBC 202   26364 value_type v; 202   26364 value_type v;
203   203  
HITCBC 204   26364 auto begin = it; 204   26364 auto begin = it;
HITCBC 205   26364 auto rv = grammar::parse( 205   26364 auto rv = grammar::parse(
206   it, end, token_rule); 206   it, end, token_rule);
HITCBC 207   26364 if( rv.has_error() || (it != end) ) 207   26364 if( rv.has_error() || (it != end) )
208   { 208   {
HITCBC 209   15941 if( it != begin ) 209   15941 if( it != begin )
210   { 210   {
HITCBC 211   15875 v = core::string_view(begin, it - begin); 211   15875 v = core::string_view(begin, it - begin);
HITCBC 212   15875 return v; 212   15875 return v;
213   } 213   }
HITCBC 214   132 return make_error_code( 214   132 return make_error_code(
HITCBC 215   66 error::bad_field_name); 215   66 error::bad_field_name);
216   } 216   }
217   217  
HITCBC 218   10423 v = core::string_view(begin, end - begin); 218   10423 v = core::string_view(begin, end - begin);
HITCBC 219   10423 return v; 219   10423 return v;
220   } 220   }
221   221  
222   auto 222   auto
HITCBC 223   16144 field_value_rule_t:: 223   16144 field_value_rule_t::
224   parse( 224   parse(
225   char const*& it, 225   char const*& it,
226   char const* end) const noexcept -> 226   char const* end) const noexcept ->
227   system::result<value_type> 227   system::result<value_type>
228   { 228   {
HITCBC 229   16144 value_type v; 229   16144 value_type v;
HITCBC 230   16144 if( it == end ) 230   16144 if( it == end )
231   { 231   {
HITCBC 232   693 v.value = core::string_view(it, 0); 232   693 v.value = core::string_view(it, 0);
HITCBC 233   693 return v; 233   693 return v;
234   } 234   }
235   235  
236   // field-line = field-name ":" OWS field-value OWS 236   // field-line = field-name ":" OWS field-value OWS
237   // field-value = *field-content 237   // field-value = *field-content
238   // field-content = field-vchar 238   // field-content = field-vchar
239   // [ 1*( SP / HTAB / field-vchar ) field-vchar ] 239   // [ 1*( SP / HTAB / field-vchar ) field-vchar ]
240   // field-vchar = VCHAR / obs-text 240   // field-vchar = VCHAR / obs-text
241   // obs-text = %x80-FF 241   // obs-text = %x80-FF
242   // VCHAR = %x21-7E 242   // VCHAR = %x21-7E
243   // ; visible (printing) characters 243   // ; visible (printing) characters
244   244  
HITCBC 245   66585 auto is_field_vchar = [](unsigned char ch) 245   66585 auto is_field_vchar = [](unsigned char ch)
246   { 246   {
HITCBC 247   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80; 247   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80;
248   }; 248   };
249   249  
HITCBC 250   15451 char const* s0 = nullptr; 250   15451 char const* s0 = nullptr;
HITCBC 251   15451 char const* s1 = nullptr; 251   15451 char const* s1 = nullptr;
252   252  
HITCBC 253   15451 bool has_crlf = false; 253   15451 bool has_crlf = false;
HITCBC 254   15451 bool has_obs_fold = false; 254   15451 bool has_obs_fold = false;
255   255  
HITCBC 256   100095 while( it < end ) 256   100095 while( it < end )
257   { 257   {
HITCBC 258   96599 auto ch = *it; 258   96599 auto ch = *it;
HITCBC 259   96599 if( ws(ch) ) 259   96599 if( ws(ch) )
260   { 260   {
HITCBC 261   17363 ++it; 261   17363 ++it;
HITCBC 262   17363 continue; 262   17363 continue;
263   } 263   }
264   264  
HITCBC 265   79236 if( ch == '\r' ) 265   79236 if( ch == '\r' )
266   { 266   {
267   // too short to know if we have a potential obs-fold 267   // too short to know if we have a potential obs-fold
268   // occurrence 268   // occurrence
HITCBC 269   12651 if( end - it < 2 ) 269   12651 if( end - it < 2 )
HITCBC 270   592 return grammar::error::need_more; 270   592 return grammar::error::need_more;
271   271  
HITCBC 272   12059 if( it[1] != '\n' ) 272   12059 if( it[1] != '\n' )
HITCBC 273   53 goto done; 273   53 goto done;
274   274  
HITCBC 275   12006 if( end - it < 3 ) 275   12006 if( end - it < 3 )
HITCBC 276   546 return grammar::error::need_more; 276   546 return grammar::error::need_more;
277   277  
HITCBC 278   11460 if(! ws(it[2]) ) 278   11460 if(! ws(it[2]) )
279   { 279   {
HITCBC 280   10730 has_crlf = true; 280   10730 has_crlf = true;
HITCBC 281   10730 goto done; 281   10730 goto done;
282   } 282   }
283   283  
HITCBC 284   730 has_obs_fold = true; 284   730 has_obs_fold = true;
HITCBC 285   730 it = it + 3; 285   730 it = it + 3;
HITCBC 286   730 continue; 286   730 continue;
287   } 287   }
288   288  
HITCBC 289   66585 if(! is_field_vchar(ch) ) 289   66585 if(! is_field_vchar(ch) )
290   { 290   {
HITCBC 291   34 goto done; 291   34 goto done;
292   } 292   }
293   293  
HITCBC 294   66551 if(! s0 ) 294   66551 if(! s0 )
HITCBC 295   14348 s0 = it; 295   14348 s0 = it;
296   296  
HITCBC 297   66551 ++it; 297   66551 ++it;
HITCBC 298   66551 s1 = it; 298   66551 s1 = it;
299   } 299   }
300   300  
HITCBC 301   3496 done: 301   3496 done:
302   // later routines wind up doing pointer 302   // later routines wind up doing pointer
303   // subtraction using the .data() member 303   // subtraction using the .data() member
304   // of the value so we need a valid 0-len range 304   // of the value so we need a valid 0-len range
HITCBC 305   14313 if(! s0 ) 305   14313 if(! s0 )
306   { 306   {
HITCBC 307   939 s0 = it; 307   939 s0 = it;
HITCBC 308   939 s1 = s0; 308   939 s1 = s0;
309   } 309   }
310   310  
HITCBC 311   14313 v.value = core::string_view(s0, s1 - s0); 311   14313 v.value = core::string_view(s0, s1 - s0);
HITCBC 312   14313 v.has_crlf = has_crlf; 312   14313 v.has_crlf = has_crlf;
HITCBC 313   14313 v.has_obs_fold = has_obs_fold; 313   14313 v.has_obs_fold = has_obs_fold;
HITCBC 314   14313 return v; 314   14313 return v;
315   } 315   }
316   316  
317   auto 317   auto
HITCBC 318   37744 field_rule_t:: 318   37744 field_rule_t::
319   parse( 319   parse(
320   char const*& it, 320   char const*& it,
321   char const* end) const noexcept -> 321   char const* end) const noexcept ->
322   system::result<value_type> 322   system::result<value_type>
323   { 323   {
HITCBC 324   37744 if(it == end) 324   37744 if(it == end)
325   { 325   {
HITCBC 326   979 return grammar::error::need_more; 326   979 return grammar::error::need_more;
327   } 327   }
328   // check for leading CRLF 328   // check for leading CRLF
HITCBC 329   36765 if(it[0] == '\r') 329   36765 if(it[0] == '\r')
330   { 330   {
HITCBC 331   10641 ++it; 331   10641 ++it;
HITCBC 332   10641 if(it == end) 332   10641 if(it == end)
333   { 333   {
HITCBC 334   489 return grammar::error::need_more; 334   489 return grammar::error::need_more;
335   } 335   }
HITCBC 336   10152 if(*it != '\n') 336   10152 if(*it != '\n')
337   { 337   {
HITCBC 338   21 return grammar::error::mismatch; 338   21 return grammar::error::mismatch;
339   } 339   }
340   // end of fields 340   // end of fields
HITCBC 341   10131 ++it; 341   10131 ++it;
HITCBC 342   10131 return grammar::error::end_of_range; 342   10131 return grammar::error::end_of_range;
343   } 343   }
344   344  
HITCBC 345   26124 value_type v; 345   26124 value_type v;
346   auto rv = grammar::parse( 346   auto rv = grammar::parse(
HITCBC 347   26124 it, end, grammar::tuple_rule( 347   26124 it, end, grammar::tuple_rule(
348   field_name_rule, 348   field_name_rule,
HITCBC 349   26124 grammar::delim_rule(':'), 349   26124 grammar::delim_rule(':'),
350   field_value_rule, 350   field_value_rule,
HITCBC 351   26124 crlf_rule)); 351   26124 crlf_rule));
352   352  
HITCBC 353   26124 if( rv.has_error() ) 353   26124 if( rv.has_error() )
HITCBC 354   15410 return rv.error(); 354   15410 return rv.error();
355   355  
HITCBC 356   10714 auto val = rv.value(); 356   10714 auto val = rv.value();
HITCBC 357   10714 v.name = std::get<0>(val); 357   10714 v.name = std::get<0>(val);
HITCBC 358   10714 v.value = std::get<2>(val).value; 358   10714 v.value = std::get<2>(val).value;
HITCBC 359   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold; 359   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold;
360   360  
HITCBC 361   10714 return v; 361   10714 return v;
362   } 362   }
363   363  
364   //------------------------------------------------ 364   //------------------------------------------------
365   365  
366   void 366   void
HITCBC 367   244 remove_obs_fold( 367   244 remove_obs_fold(
368   char* it, 368   char* it,
369   char const* const end) noexcept 369   char const* const end) noexcept
370   { 370   {
HITCBC 371   2262 while(it != end) 371   2262 while(it != end)
372   { 372   {
HITCBC 373   2236 if(*it != '\r') 373   2236 if(*it != '\r')
374   { 374   {
HITCBC 375   1637 ++it; 375   1637 ++it;
HITCBC 376   1637 continue; 376   1637 continue;
377   } 377   }
HITCBC 378   599 if(end - it < 3) 378   599 if(end - it < 3)
HITCBC 379   218 break; 379   218 break;
HITCBC 380   381 BOOST_ASSERT(it[1] == '\n'); 380   381 BOOST_ASSERT(it[1] == '\n');
HITCBC 381   762 if( it[1] == '\n' && 381   762 if( it[1] == '\n' &&
HITCBC 382   381 ws(it[2])) 382   381 ws(it[2]))
383   { 383   {
HITCBC 384   378 it[0] = ' '; 384   378 it[0] = ' ';
HITCBC 385   378 it[1] = ' '; 385   378 it[1] = ' ';
HITCBC 386   378 it += 3; 386   378 it += 3;
387   } 387   }
388   else 388   else
389   { 389   {
HITCBC 390   3 ++it; 390   3 ++it;
391   } 391   }
392   } 392   }
HITCBC 393   244 } 393   244 }
394   394  
395   } // detail 395   } // detail
396   } // http 396   } // http
397   } // boost 397   } // boost