Skip to content

Revamp how BoringSSL generate prefix header on ObjC#21194

Merged
muxi merged 40 commits intogrpc:masterfrom
muxi:boringssl-prefix-header
Apr 21, 2020
Merged

Revamp how BoringSSL generate prefix header on ObjC#21194
muxi merged 40 commits intogrpc:masterfrom
muxi:boringssl-prefix-header

Conversation

@muxi
Copy link
Copy Markdown
Contributor

@muxi muxi commented Nov 13, 2019

The original approach was a custom script generating the headers, then inject the redefined symbols to both gRPC core and BoringSSL.

The new approach in this PR is to generate symbol prefix header script that BoringSSL provides, in Docker. The prefix header is then manually uploaded to GCS. Users download it when installing BoringSSL-GRPC podspec.

In gRPC-Core and BoringSSL-GRPC Xcode projects, the macro BORINGSSL_PREFIX=GRPC is defined to prefix all BoringSSL symbols. The macro is provided by BoringSSL, so should be a better solution than our own prefix header.

Fixes #22249, #20379

cc: @stanley-cheung

@muxi muxi added lang/ObjC release notes: no Indicates if PR should not be in release notes labels Nov 13, 2019
@muxi muxi self-assigned this Nov 13, 2019
@muxi
Copy link
Copy Markdown
Contributor Author

muxi commented Nov 20, 2019

@jtattermusch - could you take an initial look at this PR and let me know if it makes sense to you? Most of the contents here reflect our discussions in the doc.

The only caveat that I feel a bit uncomfortable is that the curl command in BoringSSL-GRPC.podspec always download the prefix symbol header from gRPC's master branch. That makes the master branch grow as time goes by and that can never go away. Not sure if it makes sense or if there's a better solution.

@@ -0,0 +1,249 @@
%YAML 1.2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this file with .template-e suffix?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure... probably created a copy with a typo. I'm removing this file.

# SOME_BORINGSSL_SYMBOL
sed -i'.back' '/^#define.*\\\\$/{N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d;}' include/openssl/*.h
# Grab prefix header from Github repo
curl -o include/openssl/boringssl_prefix_symbols.h -L https://raw.githubusercontent.com/grpc/grpc/master/src/objective-c/boringssl_prefix_headers/boringssl_prefix_symbols-${boringssl_commit}.h
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the challenge here, but this downloads the right version of boringssl_prefix_symbols (depending on boringssl's SHA) from master of our repository. That means we'd have to keep an ever-growing list of boringssl shadow headers in master of our repository forever (one version for each SHA we use), and that's not a good solution.
Also I don't like that the download command can fail and that can lead to random errors when building.
Would inlining a base64 gzip compressed version of boringssl_prefix_symbols.h fit in the podspec? I know it's dirty but it's better than the challenges of this approach.
Checking in a generated version of boringssl_prefix_symbols.h into our repo is fine, but then regenerating project could inline the base64 compressed version of it into the podspec (which make the podspec standalone).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and
gzip -c boringssl_prefix_symbols.h | base64 >boringssl_prefix_symbols.h.gz.base64 gives you a file 37KB in size.
That should be good enough for us.

$ ls -lh
total 320K
-rw-r----- 1 jtattermusch primarygroup 278K Nov 21 08:34 boringssl_prefix_symbols-7f02881e96e51f1873afcf384d02f782b48967ca.h
-rw-r----- 1 jtattermusch primarygroup  37K Nov 21 08:36 boringssl_prefix_symbols.h.gz.base64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give it a try

s.prefix_header_contents =
${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)}
# Xcode import style. We add it here so that Xcode knows where to find it.
find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <boringssl_prefix_symbols.h>;#include <openssl_grpc/boringssl_prefix_symbols.h>;g'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems dirty, can we avoid this line?

Copy link
Copy Markdown
Contributor Author

@muxi muxi Nov 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so because if users build their projects as Framework, Apple does require Framework name to be the first segment in the include statement (see Apple's doc). The only possible way to avoid it is to hack the "Header search path" of the generated gRPC-Core and BoringSSL-GRPC targets pointing to the downloaded BoringSSL repo. Not sure if it'll work for Framework (because in that case the two targets are including a header outside of the Framework's Header directory). And if it works, IMHO it's an even more dirty hack.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so just to make sure: does this basically replace all occurrences of #include <boringssl_prefix_symbols.h> with #include <openssl_grpc/boringssl_prefix_symbols.h> in all *.h, *.cc and *.c files?
If so, then fair, it's not super clean, but acceptable.

# Do the following in grpc root directory
cd ../..

docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need docker for this, it seems that generating the prefix header should work just fine on people's workstation?
It look like you need 3 non-trivial scripts upgrade_boringssl_objc.sh, Dockerfile and generate_boringssl_prefix_header.sh to update the prefix header, so I'm not sure this actually simplifies things?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using Docker for a few reasons:

  • People also use Mac for the same purpose too (this process is for ObjC). Installing dependencies on Mac is not as trivial as on Linux.
  • I tend to not mess with user's workspace. As you see the process involves building BoringSSL and creating a symbol list file. The BoringSSL in the user's workspace may have their own changes. And I do need to rm -rf the artifacts which makes me a bit uncomfortable. Docker just get rid of all those matters.
  • We are already using Docker in tools/distrib/clang_format_code.sh.

As to your question, even if we do not use Docker, it would be pretty much combining the 2 shell scripts into one; I don't think there's much to remove there other than the Docker related lines. So I don't think Docker complicate things too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue most people don't have docker installed on their macs, so arguably this doesn't really make things easier (you'd need to install docker on mac and build the images first which takes time) but it does make all the scripts more complicated.
I'd prefer if we provided a robust script for regenerating the .h file (that assumes golang a cmake are installed, both are easy to install on mac). We can look into using docker in a followup PR and see if it could further simplify things.
Also, for now just supporting regenerating the prefix .h on linux is completely acceptable - later we can make improvements.


[ $# == 1 ] || { echo "Usage: generate_boringssl_prefix_header.sh <boringssl_commit>" ; exit 1 ; }

git clone -n https://github.com/google/boringssl.git
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems completely unnecessary. You have the right commit of boringssl in third_party/boringssl already so why this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the reason was I did not find a way to cleanly copy both /tools/dockerfile/grpc_objc/generate_boringssl_prefix_header/generate_boringssl_prefix_header.sh and /third_party/boringssl into the container. To make it possible I probably need to set the Docker build context to be gRPC's root dir, but that means transferring the entire grpc directory to Docker when running docker build, which takes much more time than git clone when I tried it.

And also for the same sanity reason as above, it does not cost too much to get a clean version of BoringSSL.

@muxi muxi force-pushed the boringssl-prefix-header branch from eb8f619 to ed01a6b Compare November 22, 2019 22:19
Copy link
Copy Markdown
Contributor

@jtattermusch jtattermusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think overall this is going in the right direction but I have a few simplification requests - please see comments.

# outputs a gzip+base64 encoded version of boringssl_prefix_symbols.h because of Cocoapods'
# limit on the 'prepare_command' field length. The encoded header is put at
# /src/boringssl/boringssl_prefix_symbols.h.gz.b64. Here we decode the content and inject
# the header to correcty location in BoringSSL.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/correcty/the correct/ ?

s.prefix_header_contents =
${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)}
# Xcode import style. We add it here so that Xcode knows where to find it.
find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <boringssl_prefix_symbols.h>;#include <openssl_grpc/boringssl_prefix_symbols.h>;g'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so just to make sure: does this basically replace all occurrences of #include <boringssl_prefix_symbols.h> with #include <openssl_grpc/boringssl_prefix_symbols.h> in all *.h, *.cc and *.c files?
If so, then fair, it's not super clean, but acceptable.

# /src/boringssl/boringssl_prefix_symbols.h.gz.b64. Here we decode the content and inject
# the header to correcty location in BoringSSL.
base64 -D <<EOF | gunzip > include/openssl/boringssl_prefix_symbols.h
% for line in open("src/boringssl/boringssl_prefix_symbols.h.gz.b64", "r").readlines():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For better readability (being able to see diffs over versions etc., perhaps it would be better to check-in only the boringssl_prefix_symbols.h file as (src/boringssl/boringssl_prefix_symbols.h) and only perform the gzip compression and base64 encoding in the .template. That way the generated podspec will have the gz.b64 version of the headers, but we won't have a cryptic encoded file checked into our repository.
One would also be able to see the diffs in .h over versions, which can come very handy when trying to troubleshoot boringssl upgrades in the future (one can clearly see which symbols were added etc - very useful).

It should be pretty easy to perform gz and b64 with python code inside the template.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work, but the problem I meet right now is that python 2's gzip library has a bug that using gzip.compress(...) will report AttributeError: 'module' object has no attribute 'compress'. This does not happen on python 3. It happens on both my mac and my Linux. I'll check if Kokoro has the same error (still running as for now), but I guess a lot of the team's machines could have the same problem.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jtattermusch - did we switch to python 3? Somehow I remember we dropped python 2 last year.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignore, this is resolved

# See the License for the specific language governing permissions and
# limitations under the License.

# Generate the list of boringssl symbols that need to be shadowed based on the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the comment is out of date - looks like this is intended to be a script to perform the full update of boringssl version, not just updating the shadow list.

[ -f ssl/libssl.a ] || { echo "Failed to build libssl.a" ; exit 1 ; }
[ -f crypto/libcrypto.a ] || { echo "Failed to build libcrypto.a" ; exit 1 ; }

go run ../util/read_symbols.go ssl/libssl.a > ./symbols.txt
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: where are the steps to obtain boringssl_prefix_symbols.h coming from? Are they extracted from the boringssl build? If so, please add a note and link to the original location.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are they extracted from the boringssl build?

Yes

cpu_cost: 1000
- script: tools/distrib/check_protobuf_pod_version.sh
- script: tools/distrib/check_shadow_boringssl_symbol_list.sh
- script: tools/distrib/check_boringssl_prefix_symbol.sh
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a cleaner and faster solution would be if boringssl_prefix_symbols.h would start with
// generated by generate_boringssl_prefix_header.sh from boringssl [THE-COMMIT-SHA] (just add that line when generating the file)
and sanity check would just check that boringssl_prefix_symbols.h has the right header.
That way you could make the check in seconds and you wouldn't need to add cmake to the sanity docker file.

mkdir -p $BORINGSSL_PREFIX_HEADERS_DIR
docker run -it --rm -v $(pwd)/$BORINGSSL_PREFIX_HEADERS_DIR:/output grpc/boringssl_prefix_header $BORINGSSL_COMMIT

# Increase the minor version by 1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that this script is not idempotent - if you run it multiple times, it will keep increasing the version number.
IMHO just having a robust .sh that regenerates the boringssl_prefix_symbols.h is enough for this script.

If you want to add a script that automates the whole boringssl update process, we can look into that but there are questions to be answered first and it doesn't belong to this PR. I'd recommend turning this script into something that just generates the header file (with use of docker if you will).


docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header
mkdir -p $BORINGSSL_PREFIX_HEADERS_DIR
docker run -it --rm -v $(pwd)/$BORINGSSL_PREFIX_HEADERS_DIR:/output grpc/boringssl_prefix_header $BORINGSSL_COMMIT
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect without changing the UID, the generated file will end up being owned by root.

docker run -e TEST="$TEST" -e CHANGED_FILES="$CHANGED_FILES" -e CLANG_FORMAT_ROOT="/local-code" --rm=true -v "${REPO_ROOT}":/local-code --user "$(id -u):$(id -g)" -t grpc_clang_format /clang_format_all_the_things.sh

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stale

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stale

# Do the following in grpc root directory
cd ../..

docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue most people don't have docker installed on their macs, so arguably this doesn't really make things easier (you'd need to install docker on mac and build the images first which takes time) but it does make all the scripts more complicated.
I'd prefer if we provided a robust script for regenerating the .h file (that assumes golang a cmake are installed, both are easy to install on mac). We can look into using docker in a followup PR and see if it could further simplify things.
Also, for now just supporting regenerating the prefix .h on linux is completely acceptable - later we can make improvements.

@kris520
Copy link
Copy Markdown

kris520 commented Apr 10, 2020

Come on brother, we are looking forward to solving this problem as soon as possible.

@muxi muxi marked this pull request as ready for review April 10, 2020 20:53
@muxi
Copy link
Copy Markdown
Contributor Author

muxi commented Apr 10, 2020

@jtattermusch - Updated according to your last comments. PTAL.

@muxi muxi assigned jtattermusch and unassigned muxi Apr 10, 2020
@muxi
Copy link
Copy Markdown
Contributor Author

muxi commented Apr 16, 2020

@jtattermusch - could you take a look?

cmake ..
make -j

[ -f ssl/libssl.a ] || { echo "Failed to build libssl.a" ; exit 1 ; }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a note where this magic is coming from. Without more context, this seems very arbitrary and hacky.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What magic do you mean? Do you mean the path where libssl.a is in?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for not being clearer. by "magic" I meant the sequence of commands (build, call read_symbols.go, build again, ...) that someone without context will have no idea where they came from. If you just mention you got the commands from the boringssl docs for prefixing symbols then all is fine I think.


# generates boringssl_prefix_symbols.h
cmake .. -DBORINGSSL_PREFIX=GRPC -DBORINGSSL_PREFIX_SYMBOLS=symbols.txt
make boringssl_prefix_symbols
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does boringssl provide the make boringssl_prefix_symbols? please link to boringssl docs if this is documented somewhere.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import subprocess
boringssl_commit = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd='third_party/boringssl-with-bazel').decode().strip()

import gzip, shutil, os, base64
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please include some explanation of what's the point of this snippet (I see there's some explanation below, but without more context it's not really clear that this snippet is related to that).

# We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists
find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g'
END_OF_COMMAND
# BoringSSL include boringssl_prefix_symbols.h without any prefix, which does not match the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line has an unfinished sentence, probably a typo?

# /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to
# the correct location in BoringSSL.
base64 -D <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h
${prefix_gz_b64}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: instead of using a "global" variable in the prologue, would it be more readable to actually define a function and then invoke it from here?

# /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to
# the correct location in BoringSSL.
base64 -D <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h
${prefix_gz_b64}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I looked at the generated file and it looks like it generates one extremely long line with base64.
It would be nicer if you wrapped the base64 string at 80 characters, which should still be parseable by the base64 command, but the generated file would look that ugly?

ss.dependency '${abseil_spec}', abseil_version
% endfor
ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS'
ss.compiler_flags = '-DBORINGSSL_PREFIX=GRPC'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: have you checked that the symbols are actually getting prefixed when you build like this? I don't see the boringssl_prefix_symbols.h being used anywhere in our build files so I'm just wondering what the trick is. Perhaps boringssl_prefix_symbols.h is being included by boringssl headers, which makes it transparent for grpc usage of boringssl?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I did check the symbols are prefixed, and correctly used by gRPC. The boringssl_prefix_symbols.h is used in BoringSSL headers. We just need to define the BORINGSSL_PREFIX macro when building gRPC-Core and BoringSSL-GRPC.

Copy link
Copy Markdown
Contributor

@jtattermusch jtattermusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thanks for addressing all the comments. LGTM.

@kris520
Copy link
Copy Markdown

kris520 commented Apr 21, 2020

That's great, thank you very much!

@muxi
Copy link
Copy Markdown
Contributor Author

muxi commented Apr 21, 2020

Thank you Jan.

@muxi muxi merged commit e3c5777 into grpc:master Apr 21, 2020
@muxi muxi deleted the boringssl-prefix-header branch April 21, 2020 16:27
@jiangguangpengGithub
Copy link
Copy Markdown

@muxi In this modification, the tag version of Boring-GRPC that gPRC-core depends on has been upgraded to 0.0.8, but the latest version of Boring-GRPC in the cocoapods spec is 0.0.7. May I ask when the Boring-GRPC in the cocoapods spec will be upgraded to 0.0.8?

@muxi
Copy link
Copy Markdown
Contributor Author

muxi commented Apr 23, 2020

It will be pushed to Cocoapods trunk with the next gRPC pre-release (v1.29.0-pre1). The release for v1.29.x has been blocked due to some bugs in other gRPC languages, so I cannot tell exactly when it will happen.

@jiangguangpengGithub
Copy link
Copy Markdown

Ok, thank you for your answer.

julianxhokaxhiu added a commit to julianxhokaxhiu/grpc that referenced this pull request Apr 28, 2021
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free.

This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
jtattermusch pushed a commit that referenced this pull request Aug 19, 2021
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free.

This patch essentially does what has already been done for cocoapods ( see #21194 ).
Vignesh2208 pushed a commit to Vignesh2208/grpc that referenced this pull request Aug 20, 2021
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free.

This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
lidizheng pushed a commit to lidizheng/grpc that referenced this pull request Sep 23, 2021
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free.

This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lang/ObjC release notes: no Indicates if PR should not be in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A crash related to BoringSSL

5 participants