VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-efence-allocator.cpp@ 64896

Last change on this file since 64896 was 64883, checked in by vboxsync, 8 years ago

IPRT/ASN.1: Refactored array handling (SET OF, SEQUENCE OF) to use a pointer array instead of an object instance array. The old approach would move objects around in memory after they'd be initialized/decoded, making certain core optimziations involving pointers to object members impossible, as well as causing potentially causing trouble when modifying structures that takes down pointers after decoding. Fixed validation bug in rtCrX509Name_CheckSanityExtra where it didn't check that the RDNs had subitems but instead checked the parent twice (slight risk).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: asn1-efence-allocator.cpp 64883 2016-12-15 15:26:20Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Electric Fense Allocator.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/asn1.h>
33
34#include <iprt/mem.h>
35#include <iprt/err.h>
36#include <iprt/string.h>
37
38
39/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnFree} */
40static DECLCALLBACK(void) rtAsn1EFenceAllocator_Free(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation, void *pv)
41{
42 RT_NOREF_PV(pThis);
43 RTMemEfFreeNP(pv);
44 pAllocation->cbAllocated = 0;
45}
46
47
48/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnAlloc} */
49static DECLCALLBACK(int) rtAsn1EFenceAllocator_Alloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
50 void **ppv, size_t cb)
51{
52 void *pv = RTMemEfAllocZNP(cb, RTMEM_TAG);
53 if (pv)
54 {
55 *ppv = pv;
56 pAllocation->cbAllocated = (uint32_t)cb;
57 return VINF_SUCCESS;
58 }
59 RT_NOREF_PV(pThis);
60 return VERR_NO_MEMORY;
61}
62
63
64/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnRealloc} */
65static DECLCALLBACK(int) rtAsn1EFenceAllocator_Realloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
66 void *pvOld, void **ppvNew, size_t cbNew)
67{
68 Assert(pvOld);
69 Assert(cbNew);
70 void *pv = RTMemEfReallocNP(pvOld, cbNew, RTMEM_TAG);
71 if (pv)
72 {
73 *ppvNew = pv;
74 pAllocation->cbAllocated = (uint32_t)cbNew;
75 return VINF_SUCCESS;
76 }
77 RT_NOREF_PV(pThis);
78 return VERR_NO_MEMORY;
79}
80
81
82/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnFreeArray} */
83static DECLCALLBACK(void) rtAsn1EFenceAllocator_FreeArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
84 void **papvArray)
85{
86 RT_NOREF_PV(pThis);
87 Assert(papvArray);
88 Assert(pAllocation->cbEntry);
89 Assert(pAllocation->cEntriesAllocated <= pAllocation->cPointersAllocated);
90
91 uint32_t i = pAllocation->cEntriesAllocated;
92 while (i-- > 0)
93 {
94 RTMemEfFreeNP(papvArray[i]);
95 papvArray[i] = NULL;
96 }
97 RTMemEfFreeNP(papvArray);
98
99 pAllocation->cEntriesAllocated = 0;
100 pAllocation->cPointersAllocated = 0;
101}
102
103
104/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnGrowArray} */
105static DECLCALLBACK(int) rtAsn1EFenceAllocator_GrowArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
106 void ***ppapvArray, uint32_t cMinEntries)
107{
108 RT_NOREF_PV(pThis);
109 Assert(pAllocation->cbEntry);
110 Assert(pAllocation->cEntriesAllocated <= pAllocation->cPointersAllocated);
111
112 /*
113 * Resize the pointer array.
114 */
115 void **papvArray = *ppapvArray;
116 void *pvPointers = RTMemEfReallocNP(papvArray, cMinEntries * sizeof(void *), RTMEM_TAG);
117 if (pvPointers)
118 {
119 *ppapvArray = papvArray = (void **)pvPointers;
120 if (cMinEntries > pAllocation->cPointersAllocated) /* possible on multiple shrink failures */
121 RT_BZERO(&papvArray[pAllocation->cPointersAllocated],
122 (cMinEntries - pAllocation->cPointersAllocated) * sizeof(void *));
123 else
124 AssertFailed();
125 pAllocation->cPointersAllocated = cMinEntries;
126 }
127 else if (cMinEntries > pAllocation->cPointersAllocated)
128 return VERR_NO_MEMORY;
129 /* else: possible but unlikely */
130
131 /*
132 * Add more entries.
133 */
134 while (pAllocation->cEntriesAllocated < cMinEntries)
135 {
136 void *pv;
137 papvArray[pAllocation->cEntriesAllocated] = pv = RTMemEfAllocZNP(pAllocation->cbEntry, RTMEM_TAG);
138 if (pv)
139 pAllocation->cEntriesAllocated++;
140 else
141 return VERR_NO_MEMORY;
142 }
143
144 return VINF_SUCCESS;
145}
146
147
148/** @interface_method_impl{RTASN1ALLOCATORVTABLE, pfnShrinkArray} */
149static DECLCALLBACK(void) rtAsn1EFenceAllocator_ShrinkArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
150 void ***ppapvArray, uint32_t cNew, uint32_t cCurrent)
151{
152 RT_NOREF_PV(pThis);
153 Assert(pAllocation->cbEntry);
154 Assert(pAllocation->cEntriesAllocated <= pAllocation->cPointersAllocated);
155
156 /*
157 * We always free and resize.
158 */
159 Assert(pAllocation->cEntriesAllocated == cCurrent);
160 Assert(cNew < cCurrent);
161
162 /* Free entries. */
163 void **papvArray = *ppapvArray;
164 while (cCurrent-- > cNew)
165 {
166 RTMemEfFreeNP(papvArray[cCurrent]);
167 papvArray[cCurrent] = NULL;
168 }
169 pAllocation->cEntriesAllocated = cNew;
170
171 /* Try resize pointer array. Failure here is a genuine possibility since the
172 efence code will try allocate a new block. This causes extra fun in the
173 grow method above. */
174 void *pvPointers = RTMemEfReallocNP(papvArray, cNew * sizeof(void *), RTMEM_TAG);
175 if (pvPointers)
176 {
177 *ppapvArray = (void **)pvPointers;
178 pAllocation->cPointersAllocated = cNew;
179 }
180}
181
182
183/** The Electric Fence ASN.1 allocator. */
184RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1EFenceAllocator =
185{
186 rtAsn1EFenceAllocator_Free,
187 rtAsn1EFenceAllocator_Alloc,
188 rtAsn1EFenceAllocator_Realloc,
189 rtAsn1EFenceAllocator_FreeArray,
190 rtAsn1EFenceAllocator_GrowArray,
191 rtAsn1EFenceAllocator_ShrinkArray
192};
193
194#if 0 && defined(IN_RING3) /* for efence testing */
195RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1DefaultAllocator =
196{
197 rtAsn1EFenceAllocator_Free,
198 rtAsn1EFenceAllocator_Alloc,
199 rtAsn1EFenceAllocator_Realloc,
200 rtAsn1EFenceAllocator_FreeArray,
201 rtAsn1EFenceAllocator_GrowArray,
202 rtAsn1EFenceAllocator_ShrinkArray
203};
204#endif
205
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette