]> granicus.if.org Git - clang/commitdiff
[Sema] Fix a use-after-deallocate of a ParsedAttr
authorErik Pilkington <erik.pilkington@gmail.com>
Tue, 2 Apr 2019 19:48:11 +0000 (19:48 +0000)
committerErik Pilkington <erik.pilkington@gmail.com>
Tue, 2 Apr 2019 19:48:11 +0000 (19:48 +0000)
moveAttrFromListToList only makes sense when moving an attribute to a list with
a pool that's either equivalent, or has a shorter lifetime. Therefore, using it
to move a ParsedAttr from a declarator to a declaration specifier doesn't make
sense, since the declaration specifier's pool outlives the declarator's. The
patch adds a new function, ParsedAttributes::takeOneFrom, which transfers the
attribute from one pool to another, fixing the use-after-deallocate.

rdar://49175426

Differential revision: https://reviews.llvm.org/D60101

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@357516 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/ParsedAttr.h
lib/Sema/SemaType.cpp
test/SemaObjC/arc-property-decl-attrs.m

index d125d3b8062946f6b85308fa3742e4631a550c1b..2e0efe452a80647bb7af5a297d29c0fc67ceb92f 100644 (file)
@@ -659,6 +659,7 @@ public:
 
 class AttributePool {
   friend class AttributeFactory;
+  friend class ParsedAttributes;
   AttributeFactory &Factory;
   llvm::TinyPtrVector<ParsedAttr *> Attrs;
 
@@ -892,6 +893,13 @@ public:
     pool.takeAllFrom(attrs.pool);
   }
 
+  void takeOneFrom(ParsedAttributes &Attrs, ParsedAttr *PA) {
+    Attrs.getPool().remove(PA);
+    Attrs.remove(PA);
+    getPool().add(PA);
+    addAtEnd(PA);
+  }
+
   void clear() {
     clearListOnly();
     pool.clear();
index ba028b07e3b083d7bf6d70692a13ceeae40046fa..3d3b771125f6b9e5c3c05cf04e71408f07d53f68 100644 (file)
@@ -534,8 +534,8 @@ static void distributeObjCPointerTypeAttrFromDeclarator(
       // attribute from being applied multiple times and gives
       // the source-location-filler something to work with.
       state.saveDeclSpecAttrs();
-      moveAttrFromListToList(attr, declarator.getAttributes(),
-                             declarator.getMutableDeclSpec().getAttributes());
+      declarator.getMutableDeclSpec().getAttributes().takeOneFrom(
+          declarator.getAttributes(), &attr);
       return;
     }
   }
index 6638054bef8867dcb0c107d528d43182b6af2cff..833998d4250a89d00700fe0f7a560fff07fdc81f 100644 (file)
@@ -287,3 +287,7 @@ __attribute__((objc_root_class))
 @synthesize collision = _collision; // expected-note {{property synthesized here}}
 
 @end
+
+// This used to crash because we'd temporarly store the weak attribute on the
+// declaration specifier, then deallocate it when clearing the declarator.
+id i1, __weak i2, i3;