Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix assertion in Parser.Source.to_string_trim. #1017

Merged
merged 2 commits into from
Feb 1, 2024

Conversation

mefyl
Copy link
Contributor

@mefyl mefyl commented Jan 27, 2024

I'm occasionally getting the assertion below. I didn't try reproducing, but an indexing error in to_string_trim is probably the culprit.

routine-push-notifications: internal error, uncaught exception:
                            Invalid_argument("String.sub / Bytes.sub")
                            Raised at Stdlib.invalid_arg in file "stdlib.ml", line 30, characters 20-45
                            Called from Stdlib__String.sub in file "string.ml" (inlined), line 43, characters 2-23
                            Called from Http.Parser.Source.to_string_trim in file "http/src/http.ml" (inlined), line 956, characters 6-34
                            Called from Http.Parser.header in file "http/src/http.ml", line 1053, characters 16-60
                            Called from Http.Parser.headers.loop in file "http/src/http.ml", line 1065, characters 16-29
                            Called from Http.Parser.headers.(fun) in file "http/src/http.ml" (inlined), line 1069, characters 18-32
                            Called from Http.Parser.request in file "http/src/http.ml", line 1149, characters 18-32
                            Called from Http.Parser.run_parser in file "http/src/http.ml", line 1164, characters 10-18
                            Called from Http.Parser.parse_request in file "http/src/http.ml" (inlined), line 1171, characters 36-68
                            Called from Cohttp__Request.Make.read.(fun) in file "cohttp/src/request.ml", line 176, characters 16-63
                            Called from Cohttp_eio__Io.IO.with_input_buffer in file "cohttp-eio/src/io.ml", line 20, characters 6-74
                            Called from Cohttp__Request.Make.read in file "cohttp/src/request.ml", line 175, characters 6-270

@mseri
Copy link
Collaborator

mseri commented Jan 29, 2024

Looks correct, thanks! Can you also add some tests for the function?

@mefyl
Copy link
Contributor Author

mefyl commented Jan 30, 2024

Laziness got the better of me, but you pushing me to add the test got me to the actual root of the problem so thanks for that:

  • This bug was never actually triggered since to_string_trim is always called with ~pos:0. For that reason, I can't test it with the public API, we would need to either expose the Source internals or add inline unit tests. We could also just fix it and call it a day for now since it's never actually used 😇
  • The actual bug is triggered with an empty header, which I fixed and added a test for.

@rgrinberg
Copy link
Member

@anuragsoni could you take a look?

@anuragsoni
Copy link
Contributor

This looks reasonable. The problem with the initial implementation was in the while loop that scans for whitespace leading to pos and last crossing over. Another potential change that addresses this scenario is listed below.

    let[@inline always] to_string_trim t ~pos ~len =
      if
        pos < 0
        || t.pos + pos >= t.upper_bound
        || len < 0
        || t.pos + pos + len > t.upper_bound
      then
        invalid_arg
          (Format.asprintf
             "Http_parser.Source.substring: Index out of bounds., Requested \
              off: %d, len: %d"
             pos len);
      let last = ref (t.pos + len - 1) in
      let pos = ref (t.pos + pos) in
      while is_space (String.unsafe_get t.buffer !pos) && !pos < !last do
        incr pos
      done;
      while is_space (String.unsafe_get t.buffer !last) && !last > !pos do
        decr last
      done;
      let len = !last - !pos + 1 in
      String.sub t.buffer !pos len

@mseri
Copy link
Collaborator

mseri commented Jan 31, 2024

Maybe your alternative suggestion is a bit more explicit. I don't have a strong preference between the two to be honest, do you have any preference?

@anuragsoni
Copy link
Contributor

do you have any preference?

I don't have a strong preference on this!

@mseri
Copy link
Collaborator

mseri commented Feb 1, 2024

Let's merge then, we can always amend this later if we deem it necessary

@mseri mseri merged commit 9d22421 into mirage:master Feb 1, 2024
18 of 19 checks passed
@mseri
Copy link
Collaborator

mseri commented Feb 1, 2024

Thank you all a lot!

@mefyl mefyl deleted the fix/to-string-trim branch February 1, 2024 12:55
avsm added a commit to avsm/opam-repository that referenced this pull request Nov 21, 2024
CHANGES:

- bump minimum dune version to 3.8 (@avsm)
- cohttp-eio: Use system authenticator in example.
- http, cohttp: remove the scheme field from requests. This means that
  [Request.uri] no longer returns the same URI as was to create the request
  with [Request.make] (@rgrinberg 1086)
- cohttp-eio: Remove unused `Client_intf` module (talex5 mirage/ocaml-cohttp#1081)
- cohttp-eio: Make server response type abstract and allow streaming in cohttp-eio (talex5 mirage/ocaml-cohttp#1024)
- cohttp-{lwt,eio}: server: add connection header to response if not present (ushitora-anqou mirage/ocaml-cohttp#1025)
- cohttp-curl: Curl no longer prepends the first HTTP request header to the output. (jonahbeckford mirage/ocaml-cohttp#1030, mirage/ocaml-cohttp#987)
- cohttp-eio: client: use permissive argument type for make_generic
- cohttp-eio: Improve error handling in example server (talex5 mirage/ocaml-cohttp#1023)
- cohttp-eio: Don't blow up `Server.callback` on client disconnections. (mefyl mirage/ocaml-cohttp#1015)
- http: Fix assertion in `Source.to_string_trim` when `pos <> 0` (mefyl mirage/ocaml-cohttp#1017)
- cohttp: `Cohttp.Request.make_for_client` no longer allows setting both
  `~chunked:true` and `~body_length`.
- cohttp-lwt-unix: Don't blow up when certificates are not available and no-network requests are made. (akuhlens mirage/ocaml-cohttp#1027)
  + Makes `cohttp-lwt.S.default_ctx` lazy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants