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