From 504b369f8de741241e0304f7801c84aca3ed922e Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 3 Feb 2011 10:56:31 +0000 Subject: [PATCH] Rework the __block jump-checking section, including a justification of why this bug can go uncaught. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124790 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/compatibility.html | 55 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/www/compatibility.html b/www/compatibility.html index b273487452..ddfddc7fa9 100644 --- a/www/compatibility.html +++ b/www/compatibility.html @@ -199,50 +199,51 @@ example, one could use:

Jumps to within __block variable scope

-

Clang disallows jumps into the scope of a __block variable, similar -to the manner in which both GCC and Clang disallow jumps into the scope of -variables which have user defined constructors (in C++).

- -

Variables marked with __block require special runtime initialization -before they can be used. A jump into the scope of a __block variable -would bypass this initialization and therefore the variable cannot safely be -used.

- -

For example, consider the following code fragment:

+

Clang disallows jumps into the scope of a __block +variable. Variables marked with __block require special +runtime initialization. A jump into the scope of a __block +variable bypasses this initialization, leaving the variable's metadata +in an invalid state. Consider the following code fragment:

-int f0(int c) {
-  if (c)
-    goto error;
+int fetch_object_state(struct MyObject *c) {
+  if (!c->active) goto error;
 
-  __block int x;
-  x = 1;
-  return x;
+  __block int result;
+  run_specially_somehow(^{ result = c->state; });
+  return result;
 
  error:
-  x = 0;
-  return x;
+  fprintf(stderr, "error while fetching object state");
+  return -1;
 }
 
-

GCC accepts this code, but it will crash at runtime along the error path, -because the runtime setup for the storage backing the x variable will -not have been initialized. Clang rejects this code with a hard error:

+

GCC accepts this code, but it produces code that will usually crash +when result goes out of scope if the jump is taken. (It's +possible for this bug to go undetected because it often won't crash if +the stack is fresh, i.e. still zeroed.) Therefore, Clang rejects this +code with a hard error:

 t.c:3:5: error: goto into protected scope
     goto error;
     ^
 t.c:5:15: note: jump bypasses setup of __block variable
-  __block int x;
+  __block int result;
               ^
 
-

Some instances of this construct may be safe if the variable is never used -after the jump target, however the protected scope checker does not check the -uses of the variable, only the scopes in which it is visible. You should rewrite -your code to put the __block variables in a scope which is only visible -where they are used.

+

The fix is to rewrite the code to not require jumping into a +__block variable's scope, e.g. by limiting that scope:

+ +
+  {
+    __block int result;
+    run_specially_somehow(^{ result = c->state; });
+    return result;
+  }
+

Non-initialization of __block -- 2.40.0