grpc 1.56.0 → 1.57.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (398) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +31 -22
  3. data/include/grpc/event_engine/event_engine.h +22 -32
  4. data/include/grpc/grpc_security.h +19 -0
  5. data/include/grpc/impl/grpc_types.h +3 -0
  6. data/include/grpc/support/port_platform.h +29 -23
  7. data/src/core/ext/filters/client_channel/client_channel.cc +44 -8
  8. data/src/core/ext/filters/client_channel/dynamic_filters.h +3 -3
  9. data/src/core/ext/filters/client_channel/http_proxy.cc +5 -0
  10. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +21 -52
  11. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +19 -7
  12. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +25 -35
  13. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +78 -132
  14. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +2 -1
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +4 -3
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +3 -1
  17. data/src/core/ext/filters/client_channel/lb_policy/health_check_client.cc +38 -15
  18. data/src/core/ext/filters/client_channel/lb_policy/health_check_client.h +3 -5
  19. data/src/core/ext/filters/client_channel/lb_policy/health_check_client_internal.h +22 -6
  20. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric_internal.h +2 -0
  21. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +98 -72
  22. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.h +2 -16
  23. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +56 -11
  24. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.h +25 -0
  25. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +6 -32
  26. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +4 -6
  27. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +20 -79
  28. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +1 -1
  29. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +31 -19
  30. data/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc +11 -2
  31. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +7 -41
  32. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +3 -67
  33. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h +8 -0
  34. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +31 -74
  35. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +7 -51
  36. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +16 -87
  37. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc +16 -50
  38. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_wrr_locality.cc +12 -74
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +1 -4
  40. data/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +69 -59
  41. data/src/core/ext/filters/client_channel/resolver/polling_resolver.cc +7 -2
  42. data/src/core/ext/filters/client_channel/resolver/polling_resolver.h +1 -0
  43. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +25 -13
  44. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +366 -311
  45. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h +17 -1
  46. data/src/core/ext/filters/client_channel/retry_filter.cc +39 -2498
  47. data/src/core/ext/filters/client_channel/retry_filter.h +91 -1
  48. data/src/core/ext/filters/client_channel/retry_filter_legacy_call_data.cc +2052 -0
  49. data/src/core/ext/filters/client_channel/retry_filter_legacy_call_data.h +442 -0
  50. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +38 -58
  51. data/src/core/ext/filters/client_channel/subchannel.h +3 -3
  52. data/src/core/ext/filters/client_channel/subchannel_interface_internal.h +3 -0
  53. data/src/core/ext/filters/rbac/rbac_filter.cc +40 -111
  54. data/src/core/ext/filters/rbac/rbac_filter.h +12 -30
  55. data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +162 -86
  56. data/src/core/ext/filters/stateful_session/stateful_session_filter.h +0 -6
  57. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +7 -4
  58. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +131 -186
  59. data/src/core/ext/transport/chttp2/transport/decode_huff.cc +6569 -174
  60. data/src/core/ext/transport/chttp2/transport/decode_huff.h +2278 -441
  61. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +2 -3
  62. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +176 -0
  63. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +326 -0
  64. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +569 -544
  65. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +150 -9
  66. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +47 -33
  67. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +19 -5
  68. data/src/core/ext/transport/chttp2/transport/internal.h +8 -4
  69. data/src/core/ext/transport/chttp2/transport/parsing.cc +27 -15
  70. data/src/core/ext/transport/chttp2/transport/writing.cc +2 -3
  71. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c +27 -6
  72. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h +143 -0
  73. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c +2 -9
  74. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.h +0 -39
  75. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.c +13 -8
  76. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.h +35 -6
  77. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.c +17 -13
  78. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.h +85 -20
  79. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +26 -7
  80. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +45 -3
  81. data/src/core/ext/upb-generated/envoy/config/metrics/v3/metrics_service.upb.c +4 -3
  82. data/src/core/ext/upb-generated/envoy/config/metrics/v3/metrics_service.upb.h +21 -0
  83. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c +30 -6
  84. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h +180 -0
  85. data/src/core/ext/upb-generated/envoy/data/accesslog/v3/accesslog.upb.c +558 -0
  86. data/src/core/ext/upb-generated/envoy/data/accesslog/v3/accesslog.upb.h +2710 -0
  87. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c +30 -11
  88. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h +53 -24
  89. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c +30 -5
  90. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h +110 -0
  91. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +41 -15
  92. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +150 -27
  93. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c +1 -0
  94. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.c +47 -0
  95. data/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.upb.h +93 -0
  96. data/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c +88 -76
  97. data/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h +5 -0
  98. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/config_source.upbdefs.c +11 -12
  99. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/config_source.upbdefs.h +0 -5
  100. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/grpc_service.upbdefs.c +162 -160
  101. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/health_check.upbdefs.c +129 -118
  102. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c +141 -135
  103. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/metrics_service.upbdefs.c +19 -12
  104. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c +38 -30
  105. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h +5 -0
  106. data/src/core/ext/upbdefs-generated/envoy/data/accesslog/v3/accesslog.upbdefs.c +402 -0
  107. data/src/core/ext/upbdefs-generated/envoy/data/accesslog/v3/accesslog.upbdefs.h +111 -0
  108. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c +80 -74
  109. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c +63 -47
  110. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h +5 -0
  111. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c +315 -293
  112. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h +5 -0
  113. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c +29 -29
  114. data/src/core/ext/xds/xds_bootstrap_grpc.cc +33 -30
  115. data/src/core/ext/xds/xds_bootstrap_grpc.h +5 -13
  116. data/src/core/ext/xds/xds_client_grpc.cc +11 -6
  117. data/src/core/ext/xds/xds_client_grpc.h +16 -2
  118. data/src/core/ext/xds/xds_client_stats.h +10 -0
  119. data/src/core/ext/xds/xds_cluster.cc +26 -16
  120. data/src/core/ext/xds/xds_endpoint.cc +4 -7
  121. data/src/core/ext/xds/xds_health_status.cc +0 -17
  122. data/src/core/ext/xds/xds_health_status.h +5 -25
  123. data/src/core/ext/xds/xds_lb_policy_registry.cc +39 -0
  124. data/src/core/ext/xds/xds_route_config.cc +4 -0
  125. data/src/core/ext/xds/xds_transport_grpc.cc +1 -3
  126. data/src/core/lib/address_utils/parse_address.cc +63 -1
  127. data/src/core/lib/address_utils/parse_address.h +8 -0
  128. data/src/core/lib/address_utils/sockaddr_utils.cc +46 -1
  129. data/src/core/lib/address_utils/sockaddr_utils.h +2 -2
  130. data/src/core/lib/backoff/random_early_detection.h +5 -0
  131. data/src/core/lib/channel/channel_args.cc +21 -10
  132. data/src/core/lib/channel/channel_args.h +3 -0
  133. data/src/core/lib/channel/connected_channel.cc +4 -1
  134. data/src/core/lib/channel/promise_based_filter.h +1 -0
  135. data/src/core/lib/debug/trace.cc +1 -4
  136. data/src/core/lib/event_engine/cf_engine/cf_engine.cc +2 -1
  137. data/src/core/lib/event_engine/cf_engine/cf_engine.h +1 -1
  138. data/src/core/lib/event_engine/event_engine.cc +0 -12
  139. data/src/core/lib/event_engine/forkable.cc +47 -42
  140. data/src/core/lib/event_engine/handle_containers.h +0 -4
  141. data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +4 -6
  142. data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +4 -6
  143. data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +25 -11
  144. data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +3 -1
  145. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +2 -1
  146. data/src/core/lib/event_engine/posix_engine/posix_engine.h +9 -12
  147. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +66 -27
  148. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +5 -0
  149. data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc +4 -2
  150. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +42 -2
  151. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h +6 -0
  152. data/src/core/lib/event_engine/posix_engine/timer.h +10 -37
  153. data/src/core/lib/event_engine/tcp_socket_utils.cc +67 -7
  154. data/src/core/lib/event_engine/tcp_socket_utils.h +3 -0
  155. data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +90 -37
  156. data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.h +32 -12
  157. data/src/core/lib/event_engine/thready_event_engine/thready_event_engine.cc +12 -21
  158. data/src/core/lib/event_engine/thready_event_engine/thready_event_engine.h +8 -12
  159. data/src/core/lib/event_engine/windows/windows_endpoint.cc +55 -54
  160. data/src/core/lib/event_engine/windows/windows_endpoint.h +15 -12
  161. data/src/core/lib/event_engine/windows/windows_engine.cc +2 -1
  162. data/src/core/lib/event_engine/windows/windows_engine.h +8 -12
  163. data/src/core/lib/experiments/config.cc +60 -22
  164. data/src/core/lib/experiments/config.h +20 -8
  165. data/src/core/lib/experiments/experiments.cc +278 -0
  166. data/src/core/lib/experiments/experiments.h +59 -1
  167. data/src/core/lib/gprpp/dual_ref_counted.h +9 -9
  168. data/src/core/lib/gprpp/fork.cc +8 -9
  169. data/src/core/lib/gprpp/fork.h +6 -5
  170. data/src/core/lib/gprpp/if_list.h +4530 -0
  171. data/src/core/lib/gprpp/orphanable.h +3 -3
  172. data/src/core/lib/gprpp/ref_counted.h +6 -6
  173. data/src/core/lib/gprpp/sorted_pack.h +3 -12
  174. data/src/core/lib/gprpp/status_helper.h +16 -15
  175. data/src/core/lib/gprpp/time.h +12 -0
  176. data/src/core/lib/gprpp/type_list.h +32 -0
  177. data/src/core/lib/http/httpcli.h +6 -9
  178. data/src/core/lib/iomgr/error.cc +32 -2
  179. data/src/core/lib/iomgr/error.h +9 -10
  180. data/src/core/lib/iomgr/ev_epoll1_linux.cc +5 -7
  181. data/src/core/lib/iomgr/ev_poll_posix.cc +6 -5
  182. data/src/core/lib/iomgr/exec_ctx.h +11 -0
  183. data/src/core/lib/iomgr/pollset.h +4 -5
  184. data/src/core/lib/iomgr/port.h +10 -0
  185. data/src/core/lib/iomgr/resolve_address.cc +13 -1
  186. data/src/core/lib/iomgr/resolve_address.h +17 -3
  187. data/src/core/lib/iomgr/sockaddr_posix.h +7 -0
  188. data/src/core/lib/iomgr/socket_utils_common_posix.cc +29 -0
  189. data/src/core/lib/iomgr/socket_utils_posix.cc +2 -0
  190. data/src/core/lib/iomgr/socket_utils_posix.h +6 -0
  191. data/src/core/lib/iomgr/tcp_client_posix.cc +4 -1
  192. data/src/core/lib/iomgr/tcp_posix.cc +21 -4
  193. data/src/core/lib/iomgr/tcp_server_posix.cc +37 -14
  194. data/src/core/lib/iomgr/tcp_server_utils_posix.h +12 -0
  195. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +26 -2
  196. data/src/core/lib/iomgr/tcp_windows.cc +1 -3
  197. data/src/core/lib/iomgr/vsock.cc +59 -0
  198. data/src/core/lib/iomgr/vsock.h +38 -0
  199. data/src/core/lib/iomgr/wakeup_fd_posix.h +3 -6
  200. data/src/core/lib/load_balancing/delegating_helper.h +115 -0
  201. data/src/core/lib/load_balancing/lb_policy.h +20 -0
  202. data/src/core/lib/load_balancing/subchannel_interface.h +6 -0
  203. data/src/core/lib/promise/party.h +1 -1
  204. data/src/core/lib/resolver/resolver_factory.h +3 -2
  205. data/src/core/lib/resolver/server_address.cc +9 -94
  206. data/src/core/lib/resolver/server_address.h +10 -64
  207. data/src/core/lib/resource_quota/memory_quota.h +1 -1
  208. data/src/core/lib/security/credentials/channel_creds_registry.h +51 -27
  209. data/src/core/lib/security/credentials/channel_creds_registry_init.cc +169 -9
  210. data/src/core/lib/security/credentials/composite/composite_credentials.cc +1 -1
  211. data/src/core/lib/security/credentials/composite/composite_credentials.h +3 -1
  212. data/src/core/lib/security/credentials/external/external_account_credentials.cc +40 -1
  213. data/src/core/lib/security/credentials/external/external_account_credentials.h +6 -0
  214. data/src/core/lib/security/credentials/fake/fake_credentials.cc +30 -38
  215. data/src/core/lib/security/credentials/fake/fake_credentials.h +28 -0
  216. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +8 -0
  217. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +5 -1
  218. data/src/core/lib/security/credentials/tls/tls_credentials.cc +1 -1
  219. data/src/core/lib/security/credentials/tls/tls_credentials.h +3 -1
  220. data/src/core/lib/security/security_connector/ssl_utils.cc +2 -1
  221. data/src/core/lib/security/security_connector/ssl_utils.h +1 -1
  222. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +1 -1
  223. data/src/core/lib/service_config/service_config_call_data.h +5 -0
  224. data/src/core/lib/slice/slice.h +16 -0
  225. data/src/core/lib/surface/call.cc +31 -29
  226. data/src/core/lib/surface/server.h +2 -2
  227. data/src/core/lib/surface/validate_metadata.cc +37 -22
  228. data/src/core/lib/surface/validate_metadata.h +13 -3
  229. data/src/core/lib/surface/version.cc +2 -2
  230. data/src/core/lib/transport/metadata_batch.cc +7 -7
  231. data/src/core/lib/transport/metadata_batch.h +86 -48
  232. data/src/core/lib/transport/parsed_metadata.h +34 -20
  233. data/src/core/lib/transport/simple_slice_based_metadata.h +9 -2
  234. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc +4 -6
  235. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +1 -2
  236. data/src/core/tsi/ssl_transport_security.cc +33 -9
  237. data/src/core/tsi/ssl_transport_security.h +13 -1
  238. data/src/ruby/bin/math_pb.rb +24 -18
  239. data/src/ruby/ext/grpc/extconf.rb +19 -18
  240. data/src/ruby/ext/grpc/rb_call.c +62 -39
  241. data/src/ruby/ext/grpc/rb_call_credentials.c +0 -1
  242. data/src/ruby/ext/grpc/rb_channel.c +126 -49
  243. data/src/ruby/ext/grpc/rb_channel.h +1 -0
  244. data/src/ruby/ext/grpc/rb_channel_args.c +16 -2
  245. data/src/ruby/ext/grpc/rb_channel_args.h +4 -0
  246. data/src/ruby/ext/grpc/rb_channel_credentials.c +0 -1
  247. data/src/ruby/ext/grpc/rb_compression_options.c +0 -1
  248. data/src/ruby/ext/grpc/rb_event_thread.c +22 -6
  249. data/src/ruby/ext/grpc/rb_event_thread.h +1 -0
  250. data/src/ruby/ext/grpc/rb_grpc.c +192 -30
  251. data/src/ruby/ext/grpc/rb_grpc.h +8 -2
  252. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  253. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  254. data/src/ruby/ext/grpc/rb_server.c +62 -45
  255. data/src/ruby/ext/grpc/rb_server_credentials.c +0 -1
  256. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +0 -1
  257. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +0 -1
  258. data/src/ruby/lib/grpc/generic/bidi_call.rb +2 -0
  259. data/src/ruby/lib/grpc/version.rb +1 -1
  260. data/src/ruby/pb/grpc/health/v1/health_pb.rb +24 -13
  261. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +24 -3
  262. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +25 -111
  263. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +25 -2
  264. data/third_party/boringssl-with-bazel/err_data.c +552 -552
  265. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_strnid.c +5 -5
  266. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_time.c +34 -1
  267. data/third_party/boringssl-with-bazel/src/crypto/asn1/a_utctm.c +4 -1
  268. data/third_party/boringssl-with-bazel/src/crypto/bio/bio.c +3 -3
  269. data/third_party/boringssl-with-bazel/src/crypto/bio/bio_mem.c +7 -8
  270. data/third_party/boringssl-with-bazel/src/crypto/bio/connect.c +2 -2
  271. data/third_party/boringssl-with-bazel/src/crypto/bio/fd.c +2 -2
  272. data/third_party/boringssl-with-bazel/src/crypto/bio/file.c +8 -8
  273. data/third_party/boringssl-with-bazel/src/crypto/bio/socket.c +2 -2
  274. data/third_party/boringssl-with-bazel/src/crypto/bio/socket_helper.c +2 -2
  275. data/third_party/boringssl-with-bazel/src/crypto/chacha/chacha.c +19 -1
  276. data/third_party/boringssl-with-bazel/src/crypto/chacha/internal.h +8 -1
  277. data/third_party/boringssl-with-bazel/src/crypto/conf/conf.c +28 -185
  278. data/third_party/boringssl-with-bazel/src/crypto/conf/conf_def.h +3 -7
  279. data/third_party/boringssl-with-bazel/src/crypto/conf/internal.h +8 -0
  280. data/third_party/boringssl-with-bazel/src/crypto/cpu_aarch64_apple.c +3 -0
  281. data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519.c +49 -46
  282. data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519_64_adx.c +18 -0
  283. data/third_party/boringssl-with-bazel/src/crypto/curve25519/curve25519_tables.h +2809 -7417
  284. data/third_party/boringssl-with-bazel/src/crypto/curve25519/internal.h +27 -5
  285. data/third_party/boringssl-with-bazel/src/crypto/dsa/internal.h +20 -0
  286. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_asn1.c +110 -72
  287. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/ec_derive.c +4 -3
  288. data/third_party/boringssl-with-bazel/src/crypto/ec_extra/hash_to_curve.c +15 -14
  289. data/third_party/boringssl-with-bazel/src/crypto/err/err.c +13 -10
  290. data/third_party/boringssl-with-bazel/src/crypto/evp/evp.c +35 -12
  291. data/third_party/boringssl-with-bazel/src/crypto/evp/p_ec.c +2 -4
  292. data/third_party/boringssl-with-bazel/src/crypto/evp/p_ec_asn1.c +3 -7
  293. data/third_party/boringssl-with-bazel/src/crypto/evp/pbkdf.c +3 -3
  294. data/third_party/boringssl-with-bazel/src/crypto/evp/print.c +7 -6
  295. data/third_party/boringssl-with-bazel/src/crypto/ex_data.c +34 -72
  296. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c +1 -1
  297. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/div.c +12 -5
  298. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/gcd.c +5 -6
  299. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/internal.h +12 -6
  300. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/montgomery.c +17 -18
  301. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/montgomery_inv.c +51 -15
  302. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/bn/rsaz_exp.c +7 -7
  303. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/delocate.h +5 -6
  304. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/dh/internal.h +2 -0
  305. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/builtin_curves.h +277 -0
  306. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec.c +180 -404
  307. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_key.c +3 -3
  308. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/ec_montgomery.c +24 -57
  309. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/felem.c +17 -13
  310. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/internal.h +33 -71
  311. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/oct.c +18 -17
  312. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p224-64.c +5 -7
  313. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256-nistz.c +15 -18
  314. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/p256.c +9 -11
  315. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/scalar.c +24 -24
  316. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple.c +11 -27
  317. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/simple_mul.c +8 -8
  318. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/wnaf.c +4 -4
  319. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c +9 -3
  320. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/hkdf/hkdf.c +1 -1
  321. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/fork_detect.c +40 -26
  322. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h +21 -7
  323. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +38 -19
  324. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/urandom.c +2 -29
  325. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +55 -0
  326. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +33 -52
  327. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/self_check.c +3 -8
  328. data/third_party/boringssl-with-bazel/src/crypto/internal.h +198 -79
  329. data/third_party/boringssl-with-bazel/src/crypto/kyber/kyber.c +5 -4
  330. data/third_party/boringssl-with-bazel/src/crypto/mem.c +7 -8
  331. data/third_party/boringssl-with-bazel/src/crypto/obj/obj.c +19 -23
  332. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/internal.h +3 -3
  333. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/p5_pbev2.c +3 -3
  334. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8.c +7 -7
  335. data/third_party/boringssl-with-bazel/src/crypto/pkcs8/pkcs8_x509.c +8 -5
  336. data/third_party/boringssl-with-bazel/src/crypto/pool/internal.h +1 -0
  337. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/deterministic.c +7 -6
  338. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/forkunsafe.c +6 -12
  339. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/getentropy.c +48 -0
  340. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/{fuchsia.c → ios.c} +8 -8
  341. data/third_party/boringssl-with-bazel/src/crypto/{refcount_no_threads.c → rand_extra/trusty.c} +15 -19
  342. data/third_party/boringssl-with-bazel/src/crypto/rand_extra/windows.c +41 -19
  343. data/third_party/boringssl-with-bazel/src/crypto/{refcount_c11.c → refcount.c} +11 -17
  344. data/third_party/boringssl-with-bazel/src/crypto/stack/stack.c +147 -72
  345. data/third_party/boringssl-with-bazel/src/crypto/thread_none.c +0 -8
  346. data/third_party/boringssl-with-bazel/src/crypto/thread_pthread.c +6 -35
  347. data/third_party/boringssl-with-bazel/src/crypto/thread_win.c +5 -26
  348. data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +14 -18
  349. data/third_party/boringssl-with-bazel/src/crypto/trust_token/voprf.c +54 -143
  350. data/third_party/boringssl-with-bazel/src/crypto/x509/by_dir.c +7 -13
  351. data/third_party/boringssl-with-bazel/src/crypto/x509/internal.h +1 -1
  352. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_att.c +1 -1
  353. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c +2 -4
  354. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c +2 -2
  355. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c +1 -1
  356. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_v3.c +8 -12
  357. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +19 -20
  358. data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +11 -15
  359. data/third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c +5 -5
  360. data/third_party/boringssl-with-bazel/src/crypto/x509/x_name.c +1 -1
  361. data/third_party/boringssl-with-bazel/src/crypto/x509/x_pubkey.c +7 -7
  362. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_lib.c +2 -3
  363. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_purp.c +4 -6
  364. data/third_party/boringssl-with-bazel/src/include/openssl/arm_arch.h +4 -119
  365. data/third_party/boringssl-with-bazel/src/include/openssl/asm_base.h +207 -0
  366. data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +5 -0
  367. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +2 -116
  368. data/third_party/boringssl-with-bazel/src/include/openssl/bn.h +0 -2
  369. data/third_party/boringssl-with-bazel/src/include/openssl/chacha.h +6 -0
  370. data/third_party/boringssl-with-bazel/src/include/openssl/conf.h +5 -1
  371. data/third_party/boringssl-with-bazel/src/include/openssl/dsa.h +0 -21
  372. data/third_party/boringssl-with-bazel/src/include/openssl/ec.h +21 -2
  373. data/third_party/boringssl-with-bazel/src/include/openssl/ec_key.h +19 -6
  374. data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +11 -7
  375. data/third_party/boringssl-with-bazel/src/include/openssl/rand.h +13 -14
  376. data/third_party/boringssl-with-bazel/src/include/openssl/rsa.h +0 -61
  377. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +127 -81
  378. data/third_party/boringssl-with-bazel/src/include/openssl/stack.h +224 -209
  379. data/third_party/boringssl-with-bazel/src/include/openssl/target.h +154 -0
  380. data/third_party/boringssl-with-bazel/src/include/openssl/thread.h +1 -29
  381. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +4 -4
  382. data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +3 -2
  383. data/third_party/boringssl-with-bazel/src/ssl/extensions.cc +9 -65
  384. data/third_party/boringssl-with-bazel/src/ssl/handoff.cc +20 -20
  385. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +1 -1
  386. data/third_party/boringssl-with-bazel/src/ssl/internal.h +4 -11
  387. data/third_party/boringssl-with-bazel/src/ssl/ssl_cipher.cc +24 -18
  388. data/third_party/boringssl-with-bazel/src/ssl/ssl_key_share.cc +37 -30
  389. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +125 -26
  390. data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +2 -3
  391. data/third_party/boringssl-with-bazel/src/third_party/fiat/curve25519_64_adx.h +691 -0
  392. data/third_party/upb/upb/collections/map.c +3 -3
  393. metadata +30 -13
  394. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_attributes.cc +0 -42
  395. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_attributes.h +0 -64
  396. data/src/core/ext/transport/chttp2/transport/stream_map.cc +0 -177
  397. data/src/core/ext/transport/chttp2/transport/stream_map.h +0 -68
  398. data/third_party/boringssl-with-bazel/src/crypto/refcount_win.c +0 -89
@@ -24,7 +24,7 @@
24
24
  #include <stdlib.h>
25
25
 
26
26
  #include <algorithm>
27
- #include <initializer_list>
27
+ #include <memory>
28
28
  #include <string>
29
29
  #include <utility>
30
30
 
@@ -32,21 +32,22 @@
32
32
  #include "absl/status/status.h"
33
33
  #include "absl/strings/match.h"
34
34
  #include "absl/strings/str_cat.h"
35
- #include "absl/strings/str_format.h"
36
35
  #include "absl/strings/string_view.h"
37
36
  #include "absl/types/optional.h"
38
37
  #include "absl/types/span.h"
39
38
  #include "absl/types/variant.h"
40
39
 
40
+ #include <grpc/slice.h>
41
41
  #include <grpc/support/log.h>
42
42
 
43
43
  #include "src/core/ext/transport/chttp2/transport/decode_huff.h"
44
44
  #include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
45
+ #include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
46
+ #include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
45
47
  #include "src/core/lib/debug/stats.h"
46
48
  #include "src/core/lib/debug/stats_data.h"
47
49
  #include "src/core/lib/debug/trace.h"
48
- #include "src/core/lib/gprpp/crash.h"
49
- #include "src/core/lib/gprpp/status_helper.h"
50
+ #include "src/core/lib/gprpp/match.h"
50
51
  #include "src/core/lib/slice/slice.h"
51
52
  #include "src/core/lib/slice/slice_refcount.h"
52
53
  #include "src/core/lib/surface/validate_metadata.h"
@@ -82,39 +83,6 @@ struct Base64InverseTable {
82
83
 
83
84
  constexpr Base64InverseTable kBase64InverseTable;
84
85
 
85
- absl::Status EnsureStreamError(absl::Status error) {
86
- if (error.ok()) return error;
87
- return grpc_error_set_int(std::move(error), StatusIntProperty::kStreamId, 0);
88
- }
89
-
90
- bool IsStreamError(const absl::Status& status) {
91
- intptr_t stream_id;
92
- return grpc_error_get_int(status, StatusIntProperty::kStreamId, &stream_id);
93
- }
94
-
95
- class MetadataSizeLimitExceededEncoder {
96
- public:
97
- explicit MetadataSizeLimitExceededEncoder(std::string& summary)
98
- : summary_(summary) {}
99
-
100
- void Encode(const Slice& key, const Slice& value) {
101
- AddToSummary(key.as_string_view(), value.size());
102
- }
103
-
104
- template <typename Key, typename Value>
105
- void Encode(Key, const Value& value) {
106
- AddToSummary(Key::key(), EncodedSizeOfKey(Key(), value));
107
- }
108
-
109
- private:
110
- void AddToSummary(absl::string_view key,
111
- size_t value_length) GPR_ATTRIBUTE_NOINLINE {
112
- absl::StrAppend(&summary_, " ", key, ":",
113
- hpack_constants::SizeForEntry(key.size(), value_length),
114
- "B");
115
- }
116
- std::string& summary_;
117
- };
118
86
  } // namespace
119
87
 
120
88
  // Input tracks the current byte through the input data and provides it
@@ -122,11 +90,12 @@ class MetadataSizeLimitExceededEncoder {
122
90
  class HPackParser::Input {
123
91
  public:
124
92
  Input(grpc_slice_refcount* current_slice_refcount, const uint8_t* begin,
125
- const uint8_t* end)
93
+ const uint8_t* end, HpackParseResult& error)
126
94
  : current_slice_refcount_(current_slice_refcount),
127
95
  begin_(begin),
128
96
  end_(end),
129
- frontier_(begin) {}
97
+ frontier_(begin),
98
+ error_(error) {}
130
99
 
131
100
  // If input is backed by a slice, retrieve its refcount. If not, return
132
101
  // nullptr.
@@ -156,7 +125,7 @@ class HPackParser::Input {
156
125
  // of stream
157
126
  absl::optional<uint8_t> Next() {
158
127
  if (end_of_stream()) {
159
- UnexpectedEOF();
128
+ UnexpectedEOF(/*min_progress_size=*/1);
160
129
  return absl::optional<uint8_t>();
161
130
  }
162
131
  return *begin_++;
@@ -202,9 +171,16 @@ class HPackParser::Input {
202
171
 
203
172
  // Spec weirdness: we can add an infinite stream of 0x80 at the end of a
204
173
  // varint and still end up with a correctly encoded varint.
174
+ // We allow up to 16 just for kicks, but any more and we'll assume the
175
+ // sender is being malicious.
176
+ int num_redundant_0x80 = 0;
205
177
  do {
206
178
  cur = Next();
207
179
  if (!cur.has_value()) return {};
180
+ ++num_redundant_0x80;
181
+ if (num_redundant_0x80 == 16) {
182
+ return ParseVarintMaliciousEncoding();
183
+ }
208
184
  } while (*cur == 0x80);
209
185
 
210
186
  // BUT... the last byte needs to be 0x00 or we'll overflow dramatically!
@@ -212,14 +188,6 @@ class HPackParser::Input {
212
188
  return ParseVarintOutOfRange(value, *cur);
213
189
  }
214
190
 
215
- // Prefix for a string
216
- struct StringPrefix {
217
- // Number of bytes in input for string
218
- uint32_t length;
219
- // Is it huffman compressed
220
- bool huff;
221
- };
222
-
223
191
  // Parse a string prefix
224
192
  absl::optional<StringPrefix> ParseStringPrefix() {
225
193
  auto cur = Next();
@@ -243,17 +211,13 @@ class HPackParser::Input {
243
211
  return StringPrefix{strlen, huff};
244
212
  }
245
213
 
246
- // Check if we saw an EOF.. must be verified before looking at TakeError
214
+ // Check if we saw an EOF
247
215
  bool eof_error() const {
248
- return eof_error_ || (!error_.ok() && !IsStreamError(error_));
216
+ return min_progress_size_ != 0 || error_.connection_error();
249
217
  }
250
218
 
251
- // Extract the parse error, leaving the current error as NONE.
252
- grpc_error_handle TakeError() {
253
- grpc_error_handle out = error_;
254
- error_ = absl::OkStatus();
255
- return out;
256
- }
219
+ // Minimum number of bytes to unstuck the current parse
220
+ size_t min_progress_size() const { return min_progress_size_; }
257
221
 
258
222
  bool has_error() const { return !error_.ok(); }
259
223
 
@@ -261,31 +225,55 @@ class HPackParser::Input {
261
225
  // chttp2 does not close the connection.
262
226
  // Intended for errors that are specific to a stream and recoverable.
263
227
  // Callers should ensure that any hpack table updates happen.
264
- GPR_ATTRIBUTE_NOINLINE void SetErrorAndContinueParsing(
265
- grpc_error_handle error) {
266
- GPR_ASSERT(!error.ok());
267
- // StreamId is used as a signal to skip this stream but keep the connection
268
- // alive
269
- SetError(EnsureStreamError(std::move(error)));
228
+ void SetErrorAndContinueParsing(HpackParseResult error) {
229
+ GPR_DEBUG_ASSERT(error.stream_error());
230
+ SetError(std::move(error));
270
231
  }
271
232
 
272
233
  // Set the current error, and skip past remaining bytes.
273
234
  // Intended for unrecoverable errors, with the expectation that they will
274
235
  // close the connection on return to chttp2.
275
- GPR_ATTRIBUTE_NOINLINE void SetErrorAndStopParsing(grpc_error_handle error) {
276
- GPR_ASSERT(!error.ok());
236
+ void SetErrorAndStopParsing(HpackParseResult error) {
237
+ GPR_DEBUG_ASSERT(error.connection_error());
277
238
  SetError(std::move(error));
278
239
  begin_ = end_;
279
240
  }
280
241
 
281
- // Set the error to an unexpected eof
282
- void UnexpectedEOF() {
283
- if (!error_.ok() && !IsStreamError(error_)) return;
284
- eof_error_ = true;
242
+ // Set the error to an unexpected eof.
243
+ // min_progress_size: how many bytes beyond the current frontier do we need to
244
+ // read prior to being able to get further in this parse.
245
+ void UnexpectedEOF(size_t min_progress_size) {
246
+ GPR_ASSERT(min_progress_size > 0);
247
+ if (min_progress_size_ != 0 || error_.connection_error()) {
248
+ GPR_DEBUG_ASSERT(eof_error());
249
+ return;
250
+ }
251
+ // Set min progress size, taking into account bytes parsed already but not
252
+ // consumed.
253
+ min_progress_size_ = min_progress_size + (begin_ - frontier_);
254
+ GPR_DEBUG_ASSERT(eof_error());
285
255
  }
286
256
 
287
257
  // Update the frontier - signifies we've successfully parsed another element
288
- void UpdateFrontier() { frontier_ = begin_; }
258
+ void UpdateFrontier() {
259
+ GPR_DEBUG_ASSERT(skip_bytes_ == 0);
260
+ frontier_ = begin_;
261
+ }
262
+
263
+ void UpdateFrontierAndSkipBytes(size_t skip_bytes) {
264
+ UpdateFrontier();
265
+ size_t remaining = end_ - begin_;
266
+ if (skip_bytes >= remaining) {
267
+ // If we have more bytes to skip than we have remaining in this buffer
268
+ // then we skip over what's there and stash that we need to skip some
269
+ // more.
270
+ skip_bytes_ = skip_bytes - remaining;
271
+ frontier_ = end_;
272
+ } else {
273
+ // Otherwise we zoom through some bytes and continue parsing.
274
+ frontier_ += skip_bytes_;
275
+ }
276
+ }
289
277
 
290
278
  // Get the frontier - for buffering should we fail due to eof
291
279
  const uint8_t* frontier() const { return frontier_; }
@@ -294,19 +282,23 @@ class HPackParser::Input {
294
282
  // Helper to set the error to out of range for ParseVarint
295
283
  absl::optional<uint32_t> ParseVarintOutOfRange(uint32_t value,
296
284
  uint8_t last_byte) {
297
- SetErrorAndStopParsing(absl::InternalError(absl::StrFormat(
298
- "integer overflow in hpack integer decoding: have 0x%08x, "
299
- "got byte 0x%02x on byte 5",
300
- value, last_byte)));
285
+ SetErrorAndStopParsing(
286
+ HpackParseResult::VarintOutOfRangeError(value, last_byte));
287
+ return absl::optional<uint32_t>();
288
+ }
289
+
290
+ // Helper to set the error in the case of a malicious encoding
291
+ absl::optional<uint32_t> ParseVarintMaliciousEncoding() {
292
+ SetErrorAndStopParsing(HpackParseResult::MaliciousVarintEncodingError());
301
293
  return absl::optional<uint32_t>();
302
294
  }
303
295
 
304
296
  // If no error is set, set it to the given error (i.e. first error wins)
305
297
  // Do not use this directly, instead use SetErrorAndContinueParsing or
306
298
  // SetErrorAndStopParsing.
307
- void SetError(grpc_error_handle error) {
308
- if (!error_.ok() || eof_error_) {
309
- if (!IsStreamError(error) && IsStreamError(error_)) {
299
+ void SetError(HpackParseResult error) {
300
+ if (!error_.ok() || min_progress_size_ > 0) {
301
+ if (error.connection_error() && !error_.connection_error()) {
310
302
  error_ = std::move(error); // connection errors dominate
311
303
  }
312
304
  return;
@@ -323,211 +315,156 @@ class HPackParser::Input {
323
315
  // Frontier denotes the first byte past successfully processed input
324
316
  const uint8_t* frontier_;
325
317
  // Current error
326
- grpc_error_handle error_;
327
- // If the error was EOF, we flag it here..
328
- bool eof_error_ = false;
318
+ HpackParseResult& error_;
319
+ // If the error was EOF, we flag it here by noting how many more bytes would
320
+ // be needed to make progress
321
+ size_t min_progress_size_ = 0;
322
+ // Number of bytes that should be skipped before parsing resumes.
323
+ // (We've failed parsing a request for whatever reason, but we're still
324
+ // continuing the connection so we need to see future opcodes after this bit).
325
+ size_t skip_bytes_ = 0;
329
326
  };
330
327
 
331
- // Helper to parse a string and turn it into a slice with appropriate memory
332
- // management characteristics
333
- class HPackParser::String {
334
- public:
335
- // ParseResult carries both a ParseStatus and the parsed string
336
- struct ParseResult;
337
- // Result of parsing a string
338
- enum class ParseStatus {
339
- // Parsed OK
340
- kOk,
341
- // Parse reached end of the current frame
342
- kEof,
343
- // Parse failed due to a huffman decode error
344
- kParseHuffFailed,
345
- // Parse failed due to a base64 decode error
346
- kUnbase64Failed,
347
- };
348
-
349
- String() : value_(absl::Span<const uint8_t>()) {}
350
- String(const String&) = delete;
351
- String& operator=(const String&) = delete;
352
- String(String&& other) noexcept : value_(std::move(other.value_)) {
353
- other.value_ = absl::Span<const uint8_t>();
354
- }
355
- String& operator=(String&& other) noexcept {
356
- value_ = std::move(other.value_);
357
- other.value_ = absl::Span<const uint8_t>();
358
- return *this;
328
+ absl::string_view HPackParser::String::string_view() const {
329
+ if (auto* p = absl::get_if<Slice>(&value_)) {
330
+ return p->as_string_view();
331
+ } else if (auto* p = absl::get_if<absl::Span<const uint8_t>>(&value_)) {
332
+ return absl::string_view(reinterpret_cast<const char*>(p->data()),
333
+ p->size());
334
+ } else if (auto* p = absl::get_if<std::vector<uint8_t>>(&value_)) {
335
+ return absl::string_view(reinterpret_cast<const char*>(p->data()),
336
+ p->size());
359
337
  }
338
+ GPR_UNREACHABLE_CODE(return absl::string_view());
339
+ }
360
340
 
361
- // Take the value and leave this empty
362
- Slice Take();
363
-
364
- // Return a reference to the value as a string view
365
- absl::string_view string_view() const {
366
- if (auto* p = absl::get_if<Slice>(&value_)) {
367
- return p->as_string_view();
368
- } else if (auto* p = absl::get_if<absl::Span<const uint8_t>>(&value_)) {
369
- return absl::string_view(reinterpret_cast<const char*>(p->data()),
370
- p->size());
371
- } else if (auto* p = absl::get_if<std::vector<uint8_t>>(&value_)) {
372
- return absl::string_view(reinterpret_cast<const char*>(p->data()),
373
- p->size());
374
- }
375
- GPR_UNREACHABLE_CODE(return absl::string_view());
341
+ template <typename Out>
342
+ HpackParseStatus HPackParser::String::ParseHuff(Input* input, uint32_t length,
343
+ Out output) {
344
+ // If there's insufficient bytes remaining, return now.
345
+ if (input->remaining() < length) {
346
+ input->UnexpectedEOF(/*min_progress_size=*/length);
347
+ return HpackParseStatus::kEof;
376
348
  }
349
+ // Grab the byte range, and iterate through it.
350
+ const uint8_t* p = input->cur_ptr();
351
+ input->Advance(length);
352
+ return HuffDecoder<Out>(output, p, p + length).Run()
353
+ ? HpackParseStatus::kOk
354
+ : HpackParseStatus::kParseHuffFailed;
355
+ }
377
356
 
378
- // Parse a non-binary string
379
- static ParseResult Parse(Input* input);
357
+ struct HPackParser::String::StringResult {
358
+ StringResult() = delete;
359
+ StringResult(HpackParseStatus status, size_t wire_size, String value)
360
+ : status(status), wire_size(wire_size), value(std::move(value)) {}
361
+ HpackParseStatus status;
362
+ size_t wire_size;
363
+ String value;
364
+ };
380
365
 
381
- // Parse a binary string
382
- static ParseResult ParseBinary(Input* input);
366
+ HPackParser::String::StringResult HPackParser::String::ParseUncompressed(
367
+ Input* input, uint32_t length, uint32_t wire_size) {
368
+ // Check there's enough bytes
369
+ if (input->remaining() < length) {
370
+ input->UnexpectedEOF(/*min_progress_size=*/length);
371
+ GPR_DEBUG_ASSERT(input->eof_error());
372
+ return StringResult{HpackParseStatus::kEof, wire_size, String{}};
373
+ }
374
+ auto* refcount = input->slice_refcount();
375
+ auto* p = input->cur_ptr();
376
+ input->Advance(length);
377
+ if (refcount != nullptr) {
378
+ return StringResult{HpackParseStatus::kOk, wire_size,
379
+ String(refcount, p, p + length)};
380
+ } else {
381
+ return StringResult{HpackParseStatus::kOk, wire_size,
382
+ String(absl::Span<const uint8_t>(p, length))};
383
+ }
384
+ }
383
385
 
384
- private:
385
- void AppendBytes(const uint8_t* data, size_t length);
386
- explicit String(std::vector<uint8_t> v) : value_(std::move(v)) {}
387
- explicit String(absl::Span<const uint8_t> v) : value_(v) {}
388
- String(grpc_slice_refcount* r, const uint8_t* begin, const uint8_t* end)
389
- : value_(Slice::FromRefcountAndBytes(r, begin, end)) {}
390
-
391
- // Parse some huffman encoded bytes, using output(uint8_t b) to emit each
392
- // decoded byte.
393
- template <typename Out>
394
- static ParseStatus ParseHuff(Input* input, uint32_t length, Out output) {
395
- // If there's insufficient bytes remaining, return now.
396
- if (input->remaining() < length) {
397
- input->UnexpectedEOF();
398
- GPR_DEBUG_ASSERT(input->eof_error());
399
- return ParseStatus::kEof;
400
- }
401
- // Grab the byte range, and iterate through it.
402
- const uint8_t* p = input->cur_ptr();
403
- input->Advance(length);
404
- return HuffDecoder<Out>(output, p, p + length).Run()
405
- ? ParseStatus::kOk
406
- : ParseStatus::kParseHuffFailed;
386
+ absl::optional<std::vector<uint8_t>> HPackParser::String::Unbase64Loop(
387
+ const uint8_t* cur, const uint8_t* end) {
388
+ while (cur != end && end[-1] == '=') {
389
+ --end;
407
390
  }
408
391
 
409
- // Parse some uncompressed string bytes.
410
- static ParseResult ParseUncompressed(Input* input, uint32_t length,
411
- uint32_t wire_size);
392
+ std::vector<uint8_t> out;
393
+ out.reserve(3 * (end - cur) / 4 + 3);
394
+
395
+ // Decode 4 bytes at a time while we can
396
+ while (end - cur >= 4) {
397
+ uint32_t bits = kBase64InverseTable.table[*cur];
398
+ if (bits > 63) return {};
399
+ uint32_t buffer = bits << 18;
400
+ ++cur;
401
+
402
+ bits = kBase64InverseTable.table[*cur];
403
+ if (bits > 63) return {};
404
+ buffer |= bits << 12;
405
+ ++cur;
406
+
407
+ bits = kBase64InverseTable.table[*cur];
408
+ if (bits > 63) return {};
409
+ buffer |= bits << 6;
410
+ ++cur;
411
+
412
+ bits = kBase64InverseTable.table[*cur];
413
+ if (bits > 63) return {};
414
+ buffer |= bits;
415
+ ++cur;
416
+
417
+ out.insert(out.end(), {static_cast<uint8_t>(buffer >> 16),
418
+ static_cast<uint8_t>(buffer >> 8),
419
+ static_cast<uint8_t>(buffer)});
420
+ }
421
+ // Deal with the last 0, 1, 2, or 3 bytes.
422
+ switch (end - cur) {
423
+ case 0:
424
+ return out;
425
+ case 1:
426
+ return {};
427
+ case 2: {
428
+ uint32_t bits = kBase64InverseTable.table[*cur];
429
+ if (bits > 63) return {};
430
+ uint32_t buffer = bits << 18;
412
431
 
413
- // Turn base64 encoded bytes into not base64 encoded bytes.
414
- static ParseResult Unbase64(String s);
432
+ ++cur;
433
+ bits = kBase64InverseTable.table[*cur];
434
+ if (bits > 63) return {};
435
+ buffer |= bits << 12;
415
436
 
416
- // Main loop for Unbase64
417
- static absl::optional<std::vector<uint8_t>> Unbase64Loop(const uint8_t* cur,
418
- const uint8_t* end) {
419
- while (cur != end && end[-1] == '=') {
420
- --end;
437
+ if (buffer & 0xffff) return {};
438
+ out.push_back(static_cast<uint8_t>(buffer >> 16));
439
+ return out;
421
440
  }
422
-
423
- std::vector<uint8_t> out;
424
- out.reserve(3 * (end - cur) / 4 + 3);
425
-
426
- // Decode 4 bytes at a time while we can
427
- while (end - cur >= 4) {
441
+ case 3: {
428
442
  uint32_t bits = kBase64InverseTable.table[*cur];
429
443
  if (bits > 63) return {};
430
444
  uint32_t buffer = bits << 18;
431
- ++cur;
432
445
 
446
+ ++cur;
433
447
  bits = kBase64InverseTable.table[*cur];
434
448
  if (bits > 63) return {};
435
449
  buffer |= bits << 12;
436
- ++cur;
437
450
 
451
+ ++cur;
438
452
  bits = kBase64InverseTable.table[*cur];
439
453
  if (bits > 63) return {};
440
454
  buffer |= bits << 6;
441
- ++cur;
442
455
 
443
- bits = kBase64InverseTable.table[*cur];
444
- if (bits > 63) return {};
445
- buffer |= bits;
446
456
  ++cur;
447
-
448
- out.insert(out.end(), {static_cast<uint8_t>(buffer >> 16),
449
- static_cast<uint8_t>(buffer >> 8),
450
- static_cast<uint8_t>(buffer)});
457
+ if (buffer & 0xff) return {};
458
+ out.push_back(static_cast<uint8_t>(buffer >> 16));
459
+ out.push_back(static_cast<uint8_t>(buffer >> 8));
460
+ return out;
451
461
  }
452
- // Deal with the last 0, 1, 2, or 3 bytes.
453
- switch (end - cur) {
454
- case 0:
455
- return out;
456
- case 1:
457
- return {};
458
- case 2: {
459
- uint32_t bits = kBase64InverseTable.table[*cur];
460
- if (bits > 63) return {};
461
- uint32_t buffer = bits << 18;
462
-
463
- ++cur;
464
- bits = kBase64InverseTable.table[*cur];
465
- if (bits > 63) return {};
466
- buffer |= bits << 12;
467
-
468
- if (buffer & 0xffff) return {};
469
- out.push_back(static_cast<uint8_t>(buffer >> 16));
470
- return out;
471
- }
472
- case 3: {
473
- uint32_t bits = kBase64InverseTable.table[*cur];
474
- if (bits > 63) return {};
475
- uint32_t buffer = bits << 18;
476
-
477
- ++cur;
478
- bits = kBase64InverseTable.table[*cur];
479
- if (bits > 63) return {};
480
- buffer |= bits << 12;
481
-
482
- ++cur;
483
- bits = kBase64InverseTable.table[*cur];
484
- if (bits > 63) return {};
485
- buffer |= bits << 6;
486
-
487
- ++cur;
488
- if (buffer & 0xff) return {};
489
- out.push_back(static_cast<uint8_t>(buffer >> 16));
490
- out.push_back(static_cast<uint8_t>(buffer >> 8));
491
- return out;
492
- }
493
- }
494
-
495
- GPR_UNREACHABLE_CODE(return out;);
496
462
  }
497
463
 
498
- absl::variant<Slice, absl::Span<const uint8_t>, std::vector<uint8_t>> value_;
499
- };
500
-
501
- struct HPackParser::String::ParseResult {
502
- ParseResult() = delete;
503
- ParseResult(ParseStatus status, size_t wire_size, String value)
504
- : status(status), wire_size(wire_size), value(std::move(value)) {}
505
- ParseStatus status;
506
- size_t wire_size;
507
- String value;
508
- };
509
-
510
- HPackParser::String::ParseResult HPackParser::String::ParseUncompressed(
511
- Input* input, uint32_t length, uint32_t wire_size) {
512
- // Check there's enough bytes
513
- if (input->remaining() < length) {
514
- input->UnexpectedEOF();
515
- GPR_DEBUG_ASSERT(input->eof_error());
516
- return ParseResult{ParseStatus::kEof, wire_size, String{}};
517
- }
518
- auto* refcount = input->slice_refcount();
519
- auto* p = input->cur_ptr();
520
- input->Advance(length);
521
- if (refcount != nullptr) {
522
- return ParseResult{ParseStatus::kOk, wire_size,
523
- String(refcount, p, p + length)};
524
- } else {
525
- return ParseResult{ParseStatus::kOk, wire_size,
526
- String(absl::Span<const uint8_t>(p, length))};
527
- }
464
+ GPR_UNREACHABLE_CODE(return out;);
528
465
  }
529
466
 
530
- HPackParser::String::ParseResult HPackParser::String::Unbase64(String s) {
467
+ HPackParser::String::StringResult HPackParser::String::Unbase64(String s) {
531
468
  absl::optional<std::vector<uint8_t>> result;
532
469
  if (auto* p = absl::get_if<Slice>(&s.value_)) {
533
470
  result = Unbase64Loop(p->begin(), p->end());
@@ -539,46 +476,38 @@ HPackParser::String::ParseResult HPackParser::String::Unbase64(String s) {
539
476
  result = Unbase64Loop(p->data(), p->data() + p->size());
540
477
  }
541
478
  if (!result.has_value()) {
542
- return ParseResult{ParseStatus::kUnbase64Failed, s.string_view().length(),
543
- String{}};
479
+ return StringResult{HpackParseStatus::kUnbase64Failed,
480
+ s.string_view().length(), String{}};
544
481
  }
545
- return ParseResult{ParseStatus::kOk, s.string_view().length(),
546
- String(std::move(*result))};
482
+ return StringResult{HpackParseStatus::kOk, s.string_view().length(),
483
+ String(std::move(*result))};
547
484
  }
548
485
 
549
- HPackParser::String::ParseResult HPackParser::String::Parse(Input* input) {
550
- auto pfx = input->ParseStringPrefix();
551
- if (!pfx.has_value()) {
552
- GPR_DEBUG_ASSERT(input->eof_error());
553
- return ParseResult{ParseStatus::kEof, 0, String{}};
554
- }
555
- if (pfx->huff) {
486
+ HPackParser::String::StringResult HPackParser::String::Parse(Input* input,
487
+ bool is_huff,
488
+ size_t length) {
489
+ if (is_huff) {
556
490
  // Huffman coded
557
491
  std::vector<uint8_t> output;
558
- ParseStatus sts = ParseHuff(input, pfx->length,
559
- [&output](uint8_t c) { output.push_back(c); });
492
+ HpackParseStatus sts =
493
+ ParseHuff(input, length, [&output](uint8_t c) { output.push_back(c); });
560
494
  size_t wire_len = output.size();
561
- return ParseResult{sts, wire_len, String(std::move(output))};
495
+ return StringResult{sts, wire_len, String(std::move(output))};
562
496
  }
563
- return ParseUncompressed(input, pfx->length, pfx->length);
497
+ return ParseUncompressed(input, length, length);
564
498
  }
565
499
 
566
- HPackParser::String::ParseResult HPackParser::String::ParseBinary(
567
- Input* input) {
568
- auto pfx = input->ParseStringPrefix();
569
- if (!pfx.has_value()) {
570
- GPR_DEBUG_ASSERT(input->eof_error());
571
- return ParseResult{ParseStatus::kEof, 0, String{}};
572
- }
573
- if (!pfx->huff) {
574
- if (pfx->length > 0 && input->peek() == 0) {
500
+ HPackParser::String::StringResult HPackParser::String::ParseBinary(
501
+ Input* input, bool is_huff, size_t length) {
502
+ if (!is_huff) {
503
+ if (length > 0 && input->peek() == 0) {
575
504
  // 'true-binary'
576
505
  input->Advance(1);
577
- return ParseUncompressed(input, pfx->length - 1, pfx->length);
506
+ return ParseUncompressed(input, length - 1, length);
578
507
  }
579
508
  // Base64 encoded... pull out the string, then unbase64 it
580
- auto base64 = ParseUncompressed(input, pfx->length, pfx->length);
581
- if (base64.status != ParseStatus::kOk) return base64;
509
+ auto base64 = ParseUncompressed(input, length, length);
510
+ if (base64.status != HpackParseStatus::kOk) return base64;
582
511
  return Unbase64(std::move(base64.value));
583
512
  } else {
584
513
  // Huffman encoded...
@@ -587,36 +516,35 @@ HPackParser::String::ParseResult HPackParser::String::ParseBinary(
587
516
  // and what is it.
588
517
  enum class State { kUnsure, kBinary, kBase64 };
589
518
  State state = State::kUnsure;
590
- auto sts =
591
- ParseHuff(input, pfx->length, [&state, &decompressed](uint8_t c) {
592
- if (state == State::kUnsure) {
593
- // First byte... if it's zero it's binary
594
- if (c == 0) {
595
- // Save the type, and skip the zero
596
- state = State::kBinary;
597
- return;
598
- } else {
599
- // Flag base64, store this value
600
- state = State::kBase64;
601
- }
602
- }
603
- // Non-first byte, or base64 first byte
604
- decompressed.push_back(c);
605
- });
606
- if (sts != ParseStatus::kOk) {
607
- return ParseResult{sts, 0, String{}};
519
+ auto sts = ParseHuff(input, length, [&state, &decompressed](uint8_t c) {
520
+ if (state == State::kUnsure) {
521
+ // First byte... if it's zero it's binary
522
+ if (c == 0) {
523
+ // Save the type, and skip the zero
524
+ state = State::kBinary;
525
+ return;
526
+ } else {
527
+ // Flag base64, store this value
528
+ state = State::kBase64;
529
+ }
530
+ }
531
+ // Non-first byte, or base64 first byte
532
+ decompressed.push_back(c);
533
+ });
534
+ if (sts != HpackParseStatus::kOk) {
535
+ return StringResult{sts, 0, String{}};
608
536
  }
609
537
  switch (state) {
610
538
  case State::kUnsure:
611
539
  // No bytes, empty span
612
- return ParseResult{ParseStatus::kOk, 0,
613
- String(absl::Span<const uint8_t>())};
540
+ return StringResult{HpackParseStatus::kOk, 0,
541
+ String(absl::Span<const uint8_t>())};
614
542
  case State::kBinary:
615
543
  // Binary, we're done
616
544
  {
617
545
  size_t wire_len = decompressed.size();
618
- return ParseResult{ParseStatus::kOk, wire_len,
619
- String(std::move(decompressed))};
546
+ return StringResult{HpackParseStatus::kOk, wire_len,
547
+ String(std::move(decompressed))};
620
548
  }
621
549
  case State::kBase64:
622
550
  // Base64 - unpack it
@@ -629,28 +557,38 @@ HPackParser::String::ParseResult HPackParser::String::ParseBinary(
629
557
  // Parser parses one key/value pair from a byte stream.
630
558
  class HPackParser::Parser {
631
559
  public:
632
- Parser(Input* input, grpc_metadata_batch* metadata_buffer, HPackTable* table,
633
- uint8_t* dynamic_table_updates_allowed, uint32_t* frame_length,
634
- RandomEarlyDetection* metadata_early_detection, LogInfo log_info)
560
+ Parser(Input* input, grpc_metadata_batch*& metadata_buffer,
561
+ InterSliceState& state, LogInfo log_info)
635
562
  : input_(input),
636
563
  metadata_buffer_(metadata_buffer),
637
- table_(table),
638
- dynamic_table_updates_allowed_(dynamic_table_updates_allowed),
639
- frame_length_(frame_length),
640
- metadata_early_detection_(metadata_early_detection),
564
+ state_(state),
641
565
  log_info_(log_info) {}
642
566
 
643
- // Skip any priority bits, or return false on failure
644
- bool SkipPriority() {
645
- if (input_->remaining() < 5) {
646
- input_->UnexpectedEOF();
647
- return false;
567
+ bool Parse() {
568
+ switch (state_.parse_state) {
569
+ case ParseState::kTop:
570
+ return ParseTop();
571
+ case ParseState::kParsingKeyLength:
572
+ return ParseKeyLength();
573
+ case ParseState::kParsingKeyBody:
574
+ return ParseKeyBody();
575
+ case ParseState::kSkippingKeyBody:
576
+ return SkipKeyBody();
577
+ case ParseState::kParsingValueLength:
578
+ return ParseValueLength();
579
+ case ParseState::kParsingValueBody:
580
+ return ParseValueBody();
581
+ case ParseState::kSkippingValueLength:
582
+ return SkipValueLength();
583
+ case ParseState::kSkippingValueBody:
584
+ return SkipValueBody();
648
585
  }
649
- input_->Advance(5);
650
- return true;
586
+ GPR_UNREACHABLE_CODE(return false);
651
587
  }
652
588
 
653
- bool Parse() {
589
+ private:
590
+ bool ParseTop() {
591
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
654
592
  auto cur = *input_->Next();
655
593
  switch (cur >> 4) {
656
594
  // Literal header not indexed - First byte format: 0000xxxx
@@ -663,11 +601,11 @@ class HPackParser::Parser {
663
601
  case 1:
664
602
  switch (cur & 0xf) {
665
603
  case 0: // literal key
666
- return FinishHeaderOmitFromTable(ParseLiteralKey());
604
+ return StartParseLiteralKey(false);
667
605
  case 0xf: // varint encoded key index
668
- return FinishHeaderOmitFromTable(ParseVarIdxKey(0xf));
606
+ return StartVarIdxKey(0xf, false);
669
607
  default: // inline encoded key index
670
- return FinishHeaderOmitFromTable(ParseIdxKey(cur & 0xf));
608
+ return StartIdxKey(cur & 0xf, false);
671
609
  }
672
610
  // Update max table size.
673
611
  // First byte format: 001xxxxx
@@ -694,20 +632,20 @@ class HPackParser::Parser {
694
632
  case 4:
695
633
  if (cur == 0x40) {
696
634
  // literal key
697
- return FinishHeaderAndAddToTable(ParseLiteralKey());
635
+ return StartParseLiteralKey(true);
698
636
  }
699
637
  ABSL_FALLTHROUGH_INTENDED;
700
638
  case 5:
701
639
  case 6:
702
640
  // inline encoded key index
703
- return FinishHeaderAndAddToTable(ParseIdxKey(cur & 0x3f));
641
+ return StartIdxKey(cur & 0x3f, true);
704
642
  case 7:
705
643
  if (cur == 0x7f) {
706
644
  // varint encoded key index
707
- return FinishHeaderAndAddToTable(ParseVarIdxKey(0x3f));
645
+ return StartVarIdxKey(0x3f, true);
708
646
  } else {
709
647
  // inline encoded key index
710
- return FinishHeaderAndAddToTable(ParseIdxKey(cur & 0x3f));
648
+ return StartIdxKey(cur & 0x3f, true);
711
649
  }
712
650
  // Indexed Header Field Representation
713
651
  // First byte format: 1xxxxxxx
@@ -719,7 +657,7 @@ class HPackParser::Parser {
719
657
  if (cur == 0x80) {
720
658
  // illegal value.
721
659
  input_->SetErrorAndStopParsing(
722
- absl::InternalError("Illegal hpack op code"));
660
+ HpackParseResult::IllegalHpackOpCode());
723
661
  return false;
724
662
  }
725
663
  ABSL_FALLTHROUGH_INTENDED;
@@ -743,7 +681,6 @@ class HPackParser::Parser {
743
681
  GPR_UNREACHABLE_CODE(abort());
744
682
  }
745
683
 
746
- private:
747
684
  void GPR_ATTRIBUTE_NOINLINE LogHeader(const HPackTable::Memento& memento) {
748
685
  const char* type;
749
686
  switch (log_info_.type) {
@@ -757,46 +694,48 @@ class HPackParser::Parser {
757
694
  type = "???";
758
695
  break;
759
696
  }
760
- gpr_log(GPR_DEBUG, "HTTP:%d:%s:%s: %s%s", log_info_.stream_id, type,
761
- log_info_.is_client ? "CLI" : "SVR",
762
- memento.md.DebugString().c_str(),
763
- memento.parse_status.ok()
764
- ? ""
765
- : absl::StrCat(
766
- " (parse error: ", memento.parse_status.ToString(), ")")
767
- .c_str());
697
+ gpr_log(
698
+ GPR_DEBUG, "HTTP:%d:%s:%s: %s%s", log_info_.stream_id, type,
699
+ log_info_.is_client ? "CLI" : "SVR", memento.md.DebugString().c_str(),
700
+ memento.parse_status == nullptr
701
+ ? ""
702
+ : absl::StrCat(" (parse error: ",
703
+ memento.parse_status->Materialize().ToString(), ")")
704
+ .c_str());
768
705
  }
769
706
 
770
707
  void EmitHeader(const HPackTable::Memento& md) {
771
708
  // Pass up to the transport
772
- *frame_length_ += md.md.transport_size();
773
- if (!input_->has_error() &&
774
- metadata_early_detection_->MustReject(*frame_length_)) {
775
- // Reject any requests above hard metadata limit.
776
- HandleMetadataHardSizeLimitExceeded(md);
777
- }
778
- if (!md.parse_status.ok()) {
709
+ state_.frame_length += md.md.transport_size();
710
+ if (md.parse_status != nullptr) {
779
711
  // Reject any requests with invalid metadata.
780
- HandleMetadataParseError(md.parse_status);
712
+ input_->SetErrorAndContinueParsing(*md.parse_status);
781
713
  }
782
714
  if (GPR_LIKELY(metadata_buffer_ != nullptr)) {
783
715
  metadata_buffer_->Set(md.md);
784
716
  }
717
+ if (state_.metadata_early_detection.MustReject(state_.frame_length)) {
718
+ // Reject any requests above hard metadata limit.
719
+ input_->SetErrorAndContinueParsing(
720
+ HpackParseResult::HardMetadataLimitExceededError(
721
+ std::exchange(metadata_buffer_, nullptr), state_.frame_length,
722
+ state_.metadata_early_detection.hard_limit()));
723
+ }
785
724
  }
786
725
 
787
- bool FinishHeaderAndAddToTable(absl::optional<HPackTable::Memento> md) {
788
- // Allow higher code to just pass in failures ... simplifies things a bit.
789
- if (!md.has_value()) return false;
726
+ bool FinishHeaderAndAddToTable(HPackTable::Memento md) {
790
727
  // Log if desired
791
728
  if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) {
792
- LogHeader(*md);
729
+ LogHeader(md);
793
730
  }
794
731
  // Emit whilst we own the metadata.
795
- EmitHeader(*md);
732
+ EmitHeader(md);
796
733
  // Add to the hpack table
797
- grpc_error_handle err = table_->Add(std::move(*md));
798
- if (GPR_UNLIKELY(!err.ok())) {
799
- input_->SetErrorAndStopParsing(std::move(err));
734
+ if (GPR_UNLIKELY(!state_.hpack_table.Add(std::move(md)))) {
735
+ input_->SetErrorAndStopParsing(
736
+ HpackParseResult::AddBeforeTableSizeUpdated(
737
+ state_.hpack_table.current_table_bytes(),
738
+ state_.hpack_table.max_bytes()));
800
739
  return false;
801
740
  };
802
741
  return true;
@@ -817,136 +756,269 @@ class HPackParser::Parser {
817
756
  EmitHeader(md);
818
757
  }
819
758
 
820
- // Helper type to build a memento from a key & value, and to consolidate some
821
- // tricky error path code.
822
- class MementoBuilder {
823
- public:
824
- explicit MementoBuilder(Input* input, absl::string_view key_string,
825
- absl::Status status = absl::OkStatus())
826
- : input_(input), key_string_(key_string), status_(std::move(status)) {}
827
-
828
- auto ErrorHandler() {
829
- return [this](absl::string_view error, const Slice&) {
830
- auto message =
831
- absl::StrCat("Error parsing '", key_string_,
832
- "' metadata: error=", error, " key=", key_string_);
833
- gpr_log(GPR_ERROR, "%s", message.c_str());
834
- if (status_.ok()) {
835
- status_ = absl::InternalError(message);
836
- }
837
- };
759
+ // Parse an index encoded key and a string encoded value
760
+ bool StartIdxKey(uint32_t index, bool add_to_table) {
761
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
762
+ input_->UpdateFrontier();
763
+ const auto* elem = state_.hpack_table.Lookup(index);
764
+ if (GPR_UNLIKELY(elem == nullptr)) {
765
+ InvalidHPackIndexError(index);
766
+ return false;
838
767
  }
768
+ state_.parse_state = ParseState::kParsingValueLength;
769
+ state_.is_binary_header = elem->md.is_binary_header();
770
+ state_.key.emplace<const HPackTable::Memento*>(elem);
771
+ state_.add_to_table = add_to_table;
772
+ return ParseValueLength();
773
+ };
839
774
 
840
- HPackTable::Memento Build(ParsedMetadata<grpc_metadata_batch> memento) {
841
- return HPackTable::Memento{std::move(memento), std::move(status_)};
842
- }
775
+ // Parse a varint index encoded key and a string encoded value
776
+ bool StartVarIdxKey(uint32_t offset, bool add_to_table) {
777
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
778
+ auto index = input_->ParseVarint(offset);
779
+ if (GPR_UNLIKELY(!index.has_value())) return false;
780
+ return StartIdxKey(*index, add_to_table);
781
+ }
843
782
 
844
- // Handle the result of parsing a value.
845
- // Returns true if parsing should continue, false if it should stop.
846
- // Stores an error on the input if necessary.
847
- bool HandleParseResult(String::ParseStatus status) {
848
- auto continuable = [this](absl::string_view error) {
849
- auto this_error = absl::InternalError(absl::StrCat(
850
- "Error parsing '", key_string_, "' metadata: error=", error));
851
- if (status_.ok()) status_ = this_error;
852
- input_->SetErrorAndContinueParsing(std::move(this_error));
853
- };
854
- switch (status) {
855
- case String::ParseStatus::kOk:
856
- return true;
857
- case String::ParseStatus::kParseHuffFailed:
858
- input_->SetErrorAndStopParsing(
859
- absl::InternalError("Huffman decoding failed"));
860
- return false;
861
- case String::ParseStatus::kUnbase64Failed:
862
- continuable("illegal base64 encoding");
863
- return true;
864
- case String::ParseStatus::kEof:
865
- GPR_DEBUG_ASSERT(input_->eof_error());
866
- return false;
867
- }
868
- GPR_UNREACHABLE_CODE(return false);
869
- }
783
+ bool StartParseLiteralKey(bool add_to_table) {
784
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop);
785
+ state_.add_to_table = add_to_table;
786
+ state_.parse_state = ParseState::kParsingKeyLength;
787
+ input_->UpdateFrontier();
788
+ return ParseKeyLength();
789
+ }
870
790
 
871
- private:
872
- Input* input_;
873
- absl::string_view key_string_;
874
- absl::Status status_;
875
- };
791
+ bool ShouldSkipParsingString(uint64_t string_length) const {
792
+ // We skip parsing if the string is longer than the current table size, and
793
+ // if we would have to reject the string due to metadata length limits
794
+ // regardless of what else was in the metadata batch.
795
+ //
796
+ // Why longer than the current table size? - it simplifies the logic at the
797
+ // end of skipping the string (and possibly a second if this is a key).
798
+ // If a key/value pair longer than the current table size is added to the
799
+ // hpack table we're forced to clear the entire table - this is a
800
+ // predictable operation that's easy to encode and doesn't need any state
801
+ // other than "skipping" to be carried forward.
802
+ // If we did not do this, we could end up in a situation where even though
803
+ // the metadata would overflow the current limit, it might not overflow the
804
+ // current hpack table size, and so we could not skip in on the off chance
805
+ // that we'd need to add it to the hpack table *and* reject the batch as a
806
+ // whole.
807
+ // That would be a mess, we're not doing it.
808
+ //
809
+ // These rules will end up having us parse some things that ultimately get
810
+ // rejected, and that's ok: the important thing is to have a bounded maximum
811
+ // so we can't be forced to infinitely buffer - not to have a perfect
812
+ // computation here.
813
+ return string_length > state_.hpack_table.current_table_size() &&
814
+ state_.metadata_early_detection.MustReject(
815
+ string_length + hpack_constants::kEntryOverhead);
816
+ }
817
+
818
+ bool ParseKeyLength() {
819
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingKeyLength);
820
+ auto pfx = input_->ParseStringPrefix();
821
+ if (!pfx.has_value()) return false;
822
+ state_.is_string_huff_compressed = pfx->huff;
823
+ state_.string_length = pfx->length;
824
+ input_->UpdateFrontier();
825
+ if (ShouldSkipParsingString(state_.string_length)) {
826
+ input_->SetErrorAndContinueParsing(
827
+ HpackParseResult::HardMetadataLimitExceededByKeyError(
828
+ state_.string_length,
829
+ state_.metadata_early_detection.hard_limit()));
830
+ metadata_buffer_ = nullptr;
831
+ state_.parse_state = ParseState::kSkippingKeyBody;
832
+ return SkipKeyBody();
833
+ } else {
834
+ state_.parse_state = ParseState::kParsingKeyBody;
835
+ return ParseKeyBody();
836
+ }
837
+ }
876
838
 
877
- // Parse a string encoded key and a string encoded value
878
- absl::optional<HPackTable::Memento> ParseLiteralKey() {
879
- auto key = String::Parse(input_);
839
+ bool ParseKeyBody() {
840
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingKeyBody);
841
+ auto key = String::Parse(input_, state_.is_string_huff_compressed,
842
+ state_.string_length);
880
843
  switch (key.status) {
881
- case String::ParseStatus::kOk:
844
+ case HpackParseStatus::kOk:
882
845
  break;
883
- case String::ParseStatus::kParseHuffFailed:
884
- input_->SetErrorAndStopParsing(
885
- absl::InternalError("Huffman decoding failed"));
886
- return absl::nullopt;
887
- case String::ParseStatus::kUnbase64Failed:
888
- Crash("unreachable");
889
- case String::ParseStatus::kEof:
846
+ case HpackParseStatus::kEof:
890
847
  GPR_DEBUG_ASSERT(input_->eof_error());
891
- return absl::nullopt;
848
+ return false;
849
+ default:
850
+ input_->SetErrorAndStopParsing(
851
+ HpackParseResult::FromStatus(key.status));
852
+ return false;
892
853
  }
893
- auto key_string = key.value.string_view();
894
- auto value = ParseValueString(absl::EndsWith(key_string, "-bin"));
895
- MementoBuilder builder(input_, key_string,
896
- EnsureStreamError(ValidateKey(key_string)));
897
- if (!builder.HandleParseResult(value.status)) return absl::nullopt;
898
- auto value_slice = value.value.Take();
899
- const auto transport_size =
900
- key_string.size() + value.wire_size + hpack_constants::kEntryOverhead;
901
- return builder.Build(
902
- grpc_metadata_batch::Parse(key_string, std::move(value_slice),
903
- transport_size, builder.ErrorHandler()));
854
+ input_->UpdateFrontier();
855
+ state_.parse_state = ParseState::kParsingValueLength;
856
+ state_.is_binary_header = absl::EndsWith(key.value.string_view(), "-bin");
857
+ state_.key.emplace<Slice>(key.value.Take());
858
+ return ParseValueLength();
904
859
  }
905
860
 
906
- absl::Status ValidateKey(absl::string_view key) {
907
- if (key == HttpSchemeMetadata::key() || key == HttpMethodMetadata::key() ||
908
- key == HttpAuthorityMetadata::key() || key == HttpPathMetadata::key() ||
909
- key == HttpStatusMetadata::key()) {
910
- return absl::OkStatus();
861
+ bool SkipStringBody() {
862
+ auto remaining = input_->remaining();
863
+ if (remaining >= state_.string_length) {
864
+ input_->Advance(state_.string_length);
865
+ return true;
866
+ } else {
867
+ input_->Advance(remaining);
868
+ input_->UpdateFrontier();
869
+ state_.string_length -= remaining;
870
+ // The default action of our outer loop is to buffer up to
871
+ // min_progress_size bytes.
872
+ // We know we need to do nothing up to the string length, so it would be
873
+ // legal to pass that here - however that would cause a client selected
874
+ // large buffer size to be accumulated, which would be an attack vector.
875
+ // We could also pass 1 here, and we'd be called to parse potentially
876
+ // every byte, which would give clients a way to consume substantial CPU -
877
+ // again not great.
878
+ // So we pick some tradeoff number - big enough to amortize wakeups, but
879
+ // probably not big enough to cause excessive memory use on the receiver.
880
+ input_->UnexpectedEOF(
881
+ /*min_progress_size=*/std::min(state_.string_length, 1024u));
882
+ return false;
911
883
  }
912
- return ValidateHeaderKeyIsLegal(key);
913
884
  }
914
885
 
915
- // Parse an index encoded key and a string encoded value
916
- absl::optional<HPackTable::Memento> ParseIdxKey(uint32_t index) {
917
- const auto* elem = table_->Lookup(index);
918
- if (GPR_UNLIKELY(elem == nullptr)) {
919
- InvalidHPackIndexError(index);
920
- return absl::optional<HPackTable::Memento>();
886
+ bool SkipKeyBody() {
887
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kSkippingKeyBody);
888
+ if (!SkipStringBody()) return false;
889
+ input_->UpdateFrontier();
890
+ state_.parse_state = ParseState::kSkippingValueLength;
891
+ return SkipValueLength();
892
+ }
893
+
894
+ bool SkipValueLength() {
895
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kSkippingValueLength);
896
+ auto pfx = input_->ParseStringPrefix();
897
+ if (!pfx.has_value()) return false;
898
+ state_.string_length = pfx->length;
899
+ input_->UpdateFrontier();
900
+ state_.parse_state = ParseState::kSkippingValueBody;
901
+ return SkipValueBody();
902
+ }
903
+
904
+ bool SkipValueBody() {
905
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kSkippingValueBody);
906
+ if (!SkipStringBody()) return false;
907
+ input_->UpdateFrontier();
908
+ state_.parse_state = ParseState::kTop;
909
+ if (state_.add_to_table) {
910
+ state_.hpack_table.AddLargerThanCurrentTableSize();
921
911
  }
922
- MementoBuilder builder(input_, elem->md.key(), elem->parse_status);
923
- auto value = ParseValueString(elem->md.is_binary_header());
924
- if (!builder.HandleParseResult(value.status)) return absl::nullopt;
925
- return builder.Build(elem->md.WithNewValue(
926
- value.value.Take(), value.wire_size, builder.ErrorHandler()));
927
- };
912
+ return true;
913
+ }
928
914
 
929
- // Parse a varint index encoded key and a string encoded value
930
- absl::optional<HPackTable::Memento> ParseVarIdxKey(uint32_t offset) {
931
- auto index = input_->ParseVarint(offset);
932
- if (GPR_UNLIKELY(!index.has_value())) return absl::nullopt;
933
- return ParseIdxKey(*index);
915
+ bool ParseValueLength() {
916
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingValueLength);
917
+ auto pfx = input_->ParseStringPrefix();
918
+ if (!pfx.has_value()) return false;
919
+ state_.is_string_huff_compressed = pfx->huff;
920
+ state_.string_length = pfx->length;
921
+ input_->UpdateFrontier();
922
+ if (ShouldSkipParsingString(state_.string_length)) {
923
+ input_->SetErrorAndContinueParsing(
924
+ HpackParseResult::HardMetadataLimitExceededByValueError(
925
+ Match(
926
+ state_.key, [](const Slice& s) { return s.as_string_view(); },
927
+ [](const HPackTable::Memento* m) { return m->md.key(); }),
928
+ state_.string_length,
929
+ state_.metadata_early_detection.hard_limit()));
930
+ metadata_buffer_ = nullptr;
931
+ state_.parse_state = ParseState::kSkippingValueBody;
932
+ return SkipValueBody();
933
+ } else {
934
+ state_.parse_state = ParseState::kParsingValueBody;
935
+ return ParseValueBody();
936
+ }
934
937
  }
935
938
 
936
- // Parse a string, figuring out if it's binary or not by the key name.
937
- String::ParseResult ParseValueString(bool is_binary) {
938
- if (is_binary) {
939
- return String::ParseBinary(input_);
939
+ bool ParseValueBody() {
940
+ GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kParsingValueBody);
941
+ auto value =
942
+ state_.is_binary_header
943
+ ? String::ParseBinary(input_, state_.is_string_huff_compressed,
944
+ state_.string_length)
945
+ : String::Parse(input_, state_.is_string_huff_compressed,
946
+ state_.string_length);
947
+ HpackParseResult& status = state_.frame_error;
948
+ absl::string_view key_string;
949
+ if (auto* s = absl::get_if<Slice>(&state_.key)) {
950
+ key_string = s->as_string_view();
951
+ if (status.ok()) {
952
+ auto r = ValidateKey(key_string);
953
+ if (r != ValidateMetadataResult::kOk) {
954
+ input_->SetErrorAndContinueParsing(
955
+ HpackParseResult::InvalidMetadataError(r, key_string));
956
+ }
957
+ }
940
958
  } else {
941
- return String::Parse(input_);
959
+ const auto* memento = absl::get<const HPackTable::Memento*>(state_.key);
960
+ key_string = memento->md.key();
961
+ if (status.ok() && memento->parse_status != nullptr) {
962
+ input_->SetErrorAndContinueParsing(*memento->parse_status);
963
+ }
964
+ }
965
+ switch (value.status) {
966
+ case HpackParseStatus::kOk:
967
+ break;
968
+ case HpackParseStatus::kEof:
969
+ GPR_DEBUG_ASSERT(input_->eof_error());
970
+ return false;
971
+ default: {
972
+ auto result =
973
+ HpackParseResult::FromStatusWithKey(value.status, key_string);
974
+ if (result.stream_error()) {
975
+ input_->SetErrorAndContinueParsing(std::move(result));
976
+ break;
977
+ } else {
978
+ input_->SetErrorAndStopParsing(std::move(result));
979
+ return false;
980
+ }
981
+ }
982
+ }
983
+ auto value_slice = value.value.Take();
984
+ const auto transport_size =
985
+ key_string.size() + value.wire_size + hpack_constants::kEntryOverhead;
986
+ auto md = grpc_metadata_batch::Parse(
987
+ key_string, std::move(value_slice), state_.add_to_table, transport_size,
988
+ [key_string, &status, this](absl::string_view message, const Slice&) {
989
+ if (!status.ok()) return;
990
+ input_->SetErrorAndContinueParsing(
991
+ HpackParseResult::MetadataParseError(key_string));
992
+ gpr_log(GPR_ERROR, "Error parsing '%s' metadata: %s",
993
+ std::string(key_string).c_str(),
994
+ std::string(message).c_str());
995
+ });
996
+ HPackTable::Memento memento{std::move(md),
997
+ status.PersistentStreamErrorOrNullptr()};
998
+ input_->UpdateFrontier();
999
+ state_.parse_state = ParseState::kTop;
1000
+ if (state_.add_to_table) {
1001
+ return FinishHeaderAndAddToTable(std::move(memento));
1002
+ } else {
1003
+ FinishHeaderOmitFromTable(memento);
1004
+ return true;
942
1005
  }
943
1006
  }
944
1007
 
1008
+ ValidateMetadataResult ValidateKey(absl::string_view key) {
1009
+ if (key == HttpSchemeMetadata::key() || key == HttpMethodMetadata::key() ||
1010
+ key == HttpAuthorityMetadata::key() || key == HttpPathMetadata::key() ||
1011
+ key == HttpStatusMetadata::key()) {
1012
+ return ValidateMetadataResult::kOk;
1013
+ }
1014
+ return ValidateHeaderKeyIsLegal(key);
1015
+ }
1016
+
945
1017
  // Emit an indexed field
946
1018
  bool FinishIndexed(absl::optional<uint32_t> index) {
947
- *dynamic_table_updates_allowed_ = 0;
1019
+ state_.dynamic_table_updates_allowed = 0;
948
1020
  if (!index.has_value()) return false;
949
- const auto* elem = table_->Lookup(*index);
1021
+ const auto* elem = state_.hpack_table.Lookup(*index);
950
1022
  if (GPR_UNLIKELY(elem == nullptr)) {
951
1023
  InvalidHPackIndexError(*index);
952
1024
  return false;
@@ -958,15 +1030,16 @@ class HPackParser::Parser {
958
1030
  // finish parsing a max table size change
959
1031
  bool FinishMaxTableSize(absl::optional<uint32_t> size) {
960
1032
  if (!size.has_value()) return false;
961
- if (*dynamic_table_updates_allowed_ == 0) {
962
- input_->SetErrorAndStopParsing(absl::InternalError(
963
- "More than two max table size changes in a single frame"));
1033
+ if (state_.dynamic_table_updates_allowed == 0) {
1034
+ input_->SetErrorAndStopParsing(
1035
+ HpackParseResult::TooManyDynamicTableSizeChangesError());
964
1036
  return false;
965
1037
  }
966
- (*dynamic_table_updates_allowed_)--;
967
- grpc_error_handle err = table_->SetCurrentTableSize(*size);
968
- if (!err.ok()) {
969
- input_->SetErrorAndStopParsing(std::move(err));
1038
+ state_.dynamic_table_updates_allowed--;
1039
+ if (!state_.hpack_table.SetCurrentTableSize(*size)) {
1040
+ input_->SetErrorAndStopParsing(
1041
+ HpackParseResult::IllegalTableSizeChangeError(
1042
+ *size, state_.hpack_table.max_bytes()));
970
1043
  return false;
971
1044
  }
972
1045
  return true;
@@ -975,51 +1048,13 @@ class HPackParser::Parser {
975
1048
  // Set an invalid hpack index error if no error has been set. Returns result
976
1049
  // unmodified.
977
1050
  void InvalidHPackIndexError(uint32_t index) {
978
- input_->SetErrorAndStopParsing(grpc_error_set_int(
979
- grpc_error_set_int(absl::InternalError("Invalid HPACK index received"),
980
- StatusIntProperty::kIndex,
981
- static_cast<intptr_t>(index)),
982
- StatusIntProperty::kSize,
983
- static_cast<intptr_t>(this->table_->num_entries())));
984
- }
985
-
986
- GPR_ATTRIBUTE_NOINLINE
987
- void HandleMetadataParseError(const absl::Status& status) {
988
- if (metadata_buffer_ != nullptr) {
989
- metadata_buffer_->Clear();
990
- metadata_buffer_ = nullptr;
991
- }
992
- // StreamId is used as a signal to skip this stream but keep the connection
993
- // alive
994
- input_->SetErrorAndContinueParsing(status);
995
- }
996
-
997
- GPR_ATTRIBUTE_NOINLINE
998
- void HandleMetadataHardSizeLimitExceeded(const HPackTable::Memento& md) {
999
- // Collect a summary of sizes so far for debugging
1000
- // Do not collect contents, for fear of exposing PII.
1001
- std::string summary;
1002
- std::string error_message;
1003
- if (metadata_buffer_ != nullptr) {
1004
- MetadataSizeLimitExceededEncoder encoder(summary);
1005
- metadata_buffer_->Encode(&encoder);
1006
- }
1007
- summary = absl::StrCat("; adding ", md.md.key(), " (length ",
1008
- md.md.transport_size(), "B)",
1009
- summary.empty() ? "" : " to ", summary);
1010
- error_message = absl::StrCat(
1011
- "received metadata size exceeds hard limit (", *frame_length_, " vs. ",
1012
- metadata_early_detection_->hard_limit(), ")", summary);
1013
- HandleMetadataParseError(absl::ResourceExhaustedError(error_message));
1051
+ input_->SetErrorAndStopParsing(
1052
+ HpackParseResult::InvalidHpackIndexError(index));
1014
1053
  }
1015
1054
 
1016
1055
  Input* const input_;
1017
- grpc_metadata_batch* metadata_buffer_;
1018
- HPackTable* const table_;
1019
- uint8_t* const dynamic_table_updates_allowed_;
1020
- uint32_t* const frame_length_;
1021
- // Random early detection of metadata size limits.
1022
- RandomEarlyDetection* metadata_early_detection_;
1056
+ grpc_metadata_batch*& metadata_buffer_;
1057
+ InterSliceState& state_;
1023
1058
  const LogInfo log_info_;
1024
1059
  };
1025
1060
 
@@ -1051,9 +1086,8 @@ void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
1051
1086
  }
1052
1087
  boundary_ = boundary;
1053
1088
  priority_ = priority;
1054
- dynamic_table_updates_allowed_ = 2;
1055
- frame_length_ = 0;
1056
- metadata_early_detection_ = RandomEarlyDetection(
1089
+ state_.dynamic_table_updates_allowed = 2;
1090
+ state_.metadata_early_detection.SetLimits(
1057
1091
  /*soft_limit=*/metadata_size_soft_limit,
1058
1092
  /*hard_limit=*/metadata_size_hard_limit);
1059
1093
  log_info_ = log_info;
@@ -1061,36 +1095,43 @@ void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
1061
1095
 
1062
1096
  grpc_error_handle HPackParser::Parse(const grpc_slice& slice, bool is_last) {
1063
1097
  if (GPR_UNLIKELY(!unparsed_bytes_.empty())) {
1098
+ unparsed_bytes_.insert(unparsed_bytes_.end(), GRPC_SLICE_START_PTR(slice),
1099
+ GRPC_SLICE_END_PTR(slice));
1100
+ if (!(is_last && is_boundary()) &&
1101
+ unparsed_bytes_.size() < min_progress_size_) {
1102
+ // We wouldn't make progress anyway, skip out.
1103
+ return absl::OkStatus();
1104
+ }
1064
1105
  std::vector<uint8_t> buffer = std::move(unparsed_bytes_);
1065
- buffer.insert(buffer.end(), GRPC_SLICE_START_PTR(slice),
1066
- GRPC_SLICE_END_PTR(slice));
1067
- return ParseInput(
1068
- Input(nullptr, buffer.data(), buffer.data() + buffer.size()), is_last);
1106
+ return ParseInput(Input(nullptr, buffer.data(),
1107
+ buffer.data() + buffer.size(), state_.frame_error),
1108
+ is_last);
1069
1109
  }
1070
1110
  return ParseInput(Input(slice.refcount, GRPC_SLICE_START_PTR(slice),
1071
- GRPC_SLICE_END_PTR(slice)),
1111
+ GRPC_SLICE_END_PTR(slice), state_.frame_error),
1072
1112
  is_last);
1073
1113
  }
1074
1114
 
1075
1115
  grpc_error_handle HPackParser::ParseInput(Input input, bool is_last) {
1076
1116
  ParseInputInner(&input);
1077
- if (is_last) {
1078
- if (metadata_early_detection_.Reject(frame_length_)) {
1117
+ if (is_last && is_boundary()) {
1118
+ if (state_.metadata_early_detection.Reject(state_.frame_length)) {
1079
1119
  HandleMetadataSoftSizeLimitExceeded(&input);
1080
1120
  }
1081
- global_stats().IncrementHttp2MetadataSize(frame_length_);
1082
- }
1083
- if (input.eof_error()) {
1084
- if (GPR_UNLIKELY(is_last && is_boundary())) {
1085
- auto err = input.TakeError();
1086
- if (!err.ok() && !IsStreamError(err)) return err;
1087
- return absl::InternalError(
1088
- "Incomplete header at the end of a header/continuation sequence");
1121
+ global_stats().IncrementHttp2MetadataSize(state_.frame_length);
1122
+ if (!state_.frame_error.connection_error() &&
1123
+ (input.eof_error() || state_.parse_state != ParseState::kTop)) {
1124
+ state_.frame_error = HpackParseResult::IncompleteHeaderAtBoundaryError();
1125
+ }
1126
+ state_.frame_length = 0;
1127
+ return std::exchange(state_.frame_error, HpackParseResult()).Materialize();
1128
+ } else {
1129
+ if (input.eof_error() && !state_.frame_error.connection_error()) {
1130
+ unparsed_bytes_ = std::vector<uint8_t>(input.frontier(), input.end_ptr());
1131
+ min_progress_size_ = input.min_progress_size();
1089
1132
  }
1090
- unparsed_bytes_ = std::vector<uint8_t>(input.frontier(), input.end_ptr());
1091
- return input.TakeError();
1133
+ return state_.frame_error.Materialize();
1092
1134
  }
1093
- return input.TakeError();
1094
1135
  }
1095
1136
 
1096
1137
  void HPackParser::ParseInputInner(Input* input) {
@@ -1099,7 +1140,7 @@ void HPackParser::ParseInputInner(Input* input) {
1099
1140
  break;
1100
1141
  case Priority::Included: {
1101
1142
  if (input->remaining() < 5) {
1102
- input->UnexpectedEOF();
1143
+ input->UnexpectedEOF(/*min_progress_size=*/5);
1103
1144
  return;
1104
1145
  }
1105
1146
  input->Advance(5);
@@ -1108,10 +1149,8 @@ void HPackParser::ParseInputInner(Input* input) {
1108
1149
  }
1109
1150
  }
1110
1151
  while (!input->end_of_stream()) {
1111
- if (GPR_UNLIKELY(!Parser(input, metadata_buffer_, &table_,
1112
- &dynamic_table_updates_allowed_, &frame_length_,
1113
- &metadata_early_detection_, log_info_)
1114
- .Parse())) {
1152
+ if (GPR_UNLIKELY(
1153
+ !Parser(input, metadata_buffer_, state_, log_info_).Parse())) {
1115
1154
  return;
1116
1155
  }
1117
1156
  input->UpdateFrontier();
@@ -1121,24 +1160,10 @@ void HPackParser::ParseInputInner(Input* input) {
1121
1160
  void HPackParser::FinishFrame() { metadata_buffer_ = nullptr; }
1122
1161
 
1123
1162
  void HPackParser::HandleMetadataSoftSizeLimitExceeded(Input* input) {
1124
- // Collect a summary of sizes so far for debugging
1125
- // Do not collect contents, for fear of exposing PII.
1126
- std::string summary;
1127
- std::string error_message;
1128
- if (metadata_buffer_ != nullptr) {
1129
- MetadataSizeLimitExceededEncoder encoder(summary);
1130
- metadata_buffer_->Encode(&encoder);
1131
- }
1132
- error_message = absl::StrCat(
1133
- "received metadata size exceeds soft limit (", frame_length_, " vs. ",
1134
- metadata_early_detection_.soft_limit(),
1135
- "), rejecting requests with some random probability", summary);
1136
- if (metadata_buffer_ != nullptr) {
1137
- metadata_buffer_->Clear();
1138
- metadata_buffer_ = nullptr;
1139
- }
1140
1163
  input->SetErrorAndContinueParsing(
1141
- absl::ResourceExhaustedError(error_message));
1164
+ HpackParseResult::SoftMetadataLimitExceededError(
1165
+ std::exchange(metadata_buffer_, nullptr), state_.frame_length,
1166
+ state_.metadata_early_detection.soft_limit()));
1142
1167
  }
1143
1168
 
1144
1169
  } // namespace grpc_core