Bug 1251458 - Reinstate annotation handling in .xpt files. r=khuey.
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 26 Feb 2016 10:47:36 +1100
changeset 322015 4a66b0ddeddfb9c83f9bb628b4dd7257fe519ac2
parent 322014 8bb0fb35b8b58841713813b5c695710c0edcc660
child 322016 e46b452357990be9b9838e13086e277bedda077b
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1251458, 1248534
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1251458 - Reinstate annotation handling in .xpt files. r=khuey. Even though the .xpt files we produce never have annotations, .xpt files in the wild might have them. This partly undoes part 3 of bug 1248534.
xpcom/typelib/xpt/xpt_struct.cpp
xpcom/typelib/xpt/xpt_struct.h
xpcom/typelib/xpt/xpt_xdr.cpp
xpcom/typelib/xpt/xpt_xdr.h
--- a/xpcom/typelib/xpt/xpt_struct.cpp
+++ b/xpcom/typelib/xpt/xpt_struct.cpp
@@ -21,17 +21,17 @@ static PRBool
 DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
                   XPTInterfaceDescriptor *id);
 
 static PRBool
 DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, 
                    XPTInterfaceDescriptor *id);
 
 static PRBool
-DoAnnotations(XPTCursor *cursor);
+SkipAnnotation(XPTCursor *cursor, bool *isLast);
 
 static PRBool
 DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp);
 
 static PRBool
 DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
 
 static PRBool
@@ -118,18 +118,26 @@ XPT_DoHeader(XPTArena *arena, XPTCursor 
     if (header->num_interfaces) {
         header->interface_directory = 
             (XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, header->num_interfaces * 
                                                     sizeof(XPTInterfaceDirectoryEntry));
         if (!header->interface_directory)
             return PR_FALSE;
     }
 
-    if (!DoAnnotations(cursor))
-        return PR_FALSE;
+    /*
+     * Iterate through the annotations rather than recurring, to avoid blowing
+     * the stack on large xpt files. We don't actually store annotations, we
+     * just skip over them.
+     */
+    bool isLast;
+    do {
+        if (!SkipAnnotation(cursor, &isLast))
+            return PR_FALSE;
+    } while (!isLast);
 
     /* shouldn't be necessary now, but maybe later */
     XPT_SeekTo(cursor, ide_offset); 
 
     for (i = 0; i < header->num_interfaces; i++) {
         if (!DoInterfaceDirectoryEntry(arena, cursor, 
                                        &header->interface_directory[i]))
             return PR_FALSE;
@@ -385,23 +393,25 @@ DoTypeDescriptor(XPTArena *arena, XPTCur
       default:
         /* nothing special */
         break;
     }
     return PR_TRUE;
 }
 
 PRBool
-DoAnnotations(XPTCursor *cursor)
+SkipAnnotation(XPTCursor *cursor, bool *isLast)
 {
     uint8_t flags;
     if (!XPT_Do8(cursor, &flags))
         return PR_FALSE;
 
-    // All we handle now is a single, empty annotation.
-    if (XPT_ANN_IS_PRIVATE(flags) || !XPT_ANN_IS_LAST(flags)) {
-        fprintf(stderr, "private annotations are no longer handled\n");
-        return PR_FALSE;
+    *isLast = XPT_ANN_IS_LAST(flags);
+
+    if (XPT_ANN_IS_PRIVATE(flags)) {
+        if (!XPT_SkipStringInline(cursor) ||
+            !XPT_SkipStringInline(cursor))
+            return PR_FALSE;
     }
 
     return PR_TRUE;
 }
 
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -318,18 +318,18 @@ struct XPTMethodDescriptor {
  * PrivateAnnotation
  *
  * The tag field of the prefix discriminates among the variant record 
  * types for Annotation's.  If the tag is 0, this record is an 
  * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to 
  * indicate an array of Annotation's that's completely empty.  If the tag 
  * is 1, the record is a PrivateAnnotation. 
  *
- * WARNING: we no longer support PrivateAnnotations. Each typelib can now only
- * contain a single EmptyAnnotation.
+ * We don't actually store annotations; we just skip over them if they are
+ * present.
  */
 
 #define XPT_ANN_LAST	                0x80
 #define XPT_ANN_IS_LAST(flags)          (flags & XPT_ANN_LAST)
 #define XPT_ANN_PRIVATE                 0x40
 #define XPT_ANN_IS_PRIVATE(flags)       (flags & XPT_ANN_PRIVATE)
 
 }
--- a/xpcom/typelib/xpt/xpt_xdr.cpp
+++ b/xpcom/typelib/xpt/xpt_xdr.cpp
@@ -79,16 +79,31 @@ XPT_PUBLIC_API(PRBool)
 XPT_SeekTo(XPTCursor *cursor, uint32_t offset)
 {
     /* XXX do some real checking and update len and stuff */
     cursor->offset = offset;
     return PR_TRUE;
 }
 
 XPT_PUBLIC_API(PRBool)
+XPT_SkipStringInline(XPTCursor *cursor)
+{
+    uint16_t length;
+    if (!XPT_Do16(cursor, &length))
+        return PR_FALSE;
+
+    uint8_t byte;
+    for (uint16_t i = 0; i < length; i++)
+        if (!XPT_Do8(cursor, &byte))
+            return PR_FALSE;
+
+    return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
 XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
 {
     uint32_t offset = 0;
     if (!XPT_Do32(cursor, &offset))
         return PR_FALSE;
 
     if (!offset) {
         *identp = NULL;
--- a/xpcom/typelib/xpt/xpt_xdr.h
+++ b/xpcom/typelib/xpt/xpt_xdr.h
@@ -15,16 +15,19 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct XPTState         XPTState;
 typedef struct XPTCursor        XPTCursor;
 
 extern XPT_PUBLIC_API(PRBool)
+XPT_SkipStringInline(XPTCursor *cursor);
+
+extern XPT_PUBLIC_API(PRBool)
 XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp);
 
 extern XPT_PUBLIC_API(PRBool)
 XPT_DoIID(XPTCursor *cursor, nsID *iidp);
 
 extern XPT_PUBLIC_API(PRBool)
 XPT_Do64(XPTCursor *cursor, int64_t *u64p);