• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /*
6  * Support routines for SECItemArray data structure.
7  */
8 
9 #include "nssutil.h"
10 #include "seccomon.h"
11 #include "secitem.h"
12 #include "secerr.h"
13 #include "secport.h"
14 
15 #define NSSUTIL_VERSION_NUM \
16     (NSSUTIL_VMAJOR * 10000 + NSSUTIL_VMINOR * 100 + NSSUTIL_VPATCH)
17 #if NSSUTIL_VERSION_NUM < 31500
18 // Added in NSS 3.15.
19 typedef struct SECItemArrayStr SECItemArray;
20 
21 struct SECItemArrayStr {
22     SECItem *items;
23     unsigned int len;
24 };
25 #endif
26 
27 SECItemArray *
SECITEM_AllocArray(PLArenaPool * arena,SECItemArray * array,unsigned int len)28 SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len)
29 {
30     SECItemArray *result = NULL;
31     void *mark = NULL;
32 
33     if (arena != NULL) {
34         mark = PORT_ArenaMark(arena);
35     }
36 
37     if (array == NULL) {
38         if (arena != NULL) {
39             result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray));
40         } else {
41             result = PORT_ZAlloc(sizeof(SECItemArray));
42         }
43         if (result == NULL) {
44             goto loser;
45         }
46     } else {
47         PORT_Assert(array->items == NULL);
48         result = array;
49     }
50 
51     result->len = len;
52     if (len) {
53         if (arena != NULL) {
54             result->items = PORT_ArenaZNewArray(arena, SECItem, len);
55         } else {
56             result->items = PORT_ZNewArray(SECItem, len);
57         }
58         if (result->items == NULL) {
59             goto loser;
60         }
61     } else {
62         result->items = NULL;
63     }
64 
65     if (mark) {
66         PORT_ArenaUnmark(arena, mark);
67     }
68     return(result);
69 
70 loser:
71     if ( arena != NULL ) {
72         if (mark) {
73             PORT_ArenaRelease(arena, mark);
74         }
75         if (array != NULL) {
76             array->items = NULL;
77             array->len = 0;
78         }
79     } else {
80         if (result != NULL && array == NULL) {
81             PORT_Free(result);
82         }
83         /*
84          * If array is not NULL, the above has set array->data and
85          * array->len to 0.
86          */
87     }
88     return(NULL);
89 }
90 
91 static void
secitem_FreeArray(SECItemArray * array,PRBool zero_items,PRBool freeit)92 secitem_FreeArray(SECItemArray *array, PRBool zero_items, PRBool freeit)
93 {
94     unsigned int i;
95 
96     if (!array || !array->len || !array->items)
97         return;
98 
99     for (i=0; i<array->len; ++i) {
100         SECItem *item = &array->items[i];
101 
102         if (item->data) {
103             if (zero_items) {
104                 SECITEM_ZfreeItem(item, PR_FALSE);
105             } else {
106                 SECITEM_FreeItem(item, PR_FALSE);
107             }
108         }
109     }
110     PORT_Free(array->items);
111     array->items = NULL;
112     array->len = 0;
113 
114     if (freeit)
115         PORT_Free(array);
116 }
117 
SECITEM_FreeArray(SECItemArray * array,PRBool freeit)118 void SECITEM_FreeArray(SECItemArray *array, PRBool freeit)
119 {
120     secitem_FreeArray(array, PR_FALSE, freeit);
121 }
122 
SECITEM_ZfreeArray(SECItemArray * array,PRBool freeit)123 void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit)
124 {
125     secitem_FreeArray(array, PR_TRUE, freeit);
126 }
127 
128 SECItemArray *
SECITEM_DupArray(PLArenaPool * arena,const SECItemArray * from)129 SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from)
130 {
131     SECItemArray *result;
132     unsigned int i;
133 
134     if (!from || !from->items || !from->len)
135         return NULL;
136 
137     result = SECITEM_AllocArray(arena, NULL, from->len);
138     if (!result)
139         return NULL;
140 
141     for (i=0; i<from->len; ++i) {
142         SECStatus rv = SECITEM_CopyItem(arena,
143                                         &result->items[i], &from->items[i]);
144         if (rv != SECSuccess) {
145             SECITEM_ZfreeArray(result, PR_TRUE);
146             return NULL;
147         }
148     }
149 
150     return result;
151 }
152