Add BIO_FP_TEXT

This CL allows us to reduce the patch set on CPython.

BIO_new_fp is the FILE* analog of BIO_new_fd. However, it behaves very
strangely w.r.t. Windows file translation modes. Instead of simply
inheriting the FILE* as the caller constructed it, it unconditionally
overrides the file's translation mode!

This is surprising. Moreover, if you change the mode without flushing
the file, weird things happen, as Windows documentation discusses:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode?view=msvc-170

This leaks all the way up to calling code, because callers need to pass
a matching BIO_FP_TEXT to the FILE* they made. To be source-compatible
with such callers, notably CPython, we need to at least provide
BIO_FP_TEXT.

I first tried to fully match OpenSSL's semantics, but OpenSSL's
semantics are quite dangerous. Code tested on POSIX, calling
BIO_new_fp(some_file, BIO_NOCLOSE), without much thought, is subtly
broken on Windows. It will change the mode of any file passed into it to
binary!

Our own code runs into this. BIO_new_file internally calls BIO_new_fp.
In OpenSSL, they need to re-parse the mode string and figure out the
right flag. ASN1_STRING_print_ex_fp doesn't even know which is the right
one. In OpenSSL, they actually call fwrite manually. We wrap it in a BIO
and then use the BIO version, because it makes no sense to not use the
abstraction we already have lying around. But that is incompatible with
OpenSSL's semantics.

So instead I've opted to make BIO_FP_TEXT switch the mode, but no flag
just leaves the mode alone. This is slightly OpenSSL-incompatible
because this code will work in OpenSSL, but continue to not work in
BoringSSL:

  // Oops, I actually wanted binary but forgot to use "rb"
  FILE *f = fopen("blah", "r");
  // But bio fixed it for me!
  BIO *bio = BIO_new_fp(f, BIO_NOCLOSE);

But callers should have passed "rb" if they wanted binary. This is also
preexisting and no one has noticed. I think it's far more likely that
applications *aren't* expecting BIO_new_fp to secretly change the input
FILE's mode. If we ever need to, we can adopt OpenSSL's semantics and
then add BIO_FP_LEAVE_MY_FILE_ALONE. But those are worse defaults.

Change-Id: I2905673c523eb24312c15d3000cbe34a66602700
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66809
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
3 files changed
tree: 0be7e768538d0aea7482aad1a3b014ea1cc23e6e
  1. .github/
  2. cmake/
  3. crypto/
  4. decrepit/
  5. fuzz/
  6. include/
  7. pki/
  8. rust/
  9. ssl/
  10. third_party/
  11. tool/
  12. util/
  13. .clang-format
  14. .gitignore
  15. API-CONVENTIONS.md
  16. BREAKING-CHANGES.md
  17. BUILDING.md
  18. CMakeLists.txt
  19. codereview.settings
  20. CONTRIBUTING.md
  21. FUZZING.md
  22. go.mod
  23. go.sum
  24. INCORPORATING.md
  25. LICENSE
  26. PORTING.md
  27. README.md
  28. SANDBOXING.md
  29. sources.cmake
  30. STYLE.md
README.md

BoringSSL

BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.

Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.

Programs ship their own copies of BoringSSL when they use it and we update everything as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you.

BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily.

Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the NDK) and a number of other apps/programs.

Project links:

There are other files in this directory which might be helpful: