VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/vfs/vfsiosmisc.cpp@ 73603

Last change on this file since 73603 was 69523, checked in by vboxsync, 7 years ago

Runtime/vfs/vfsiosmisc: Fix possible memory leak

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: vfsiosmisc.cpp 69523 2017-10-30 11:08:37Z vboxsync $ */
2/** @file
3 * IPRT - Virtual File System, Misc I/O Stream Operations.
4 */
5
6/*
7 * Copyright (C) 2010-2017 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 <iprt/vfs.h>
32#include <iprt/vfslowlevel.h>
33
34#include <iprt/err.h>
35#include <iprt/mem.h>
36#include <iprt/string.h>
37
38
39
40RTDECL(int) RTVfsIoStrmValidateUtf8Encoding(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTFOFF poffError)
41{
42 /*
43 * Validate input.
44 */
45 if (poffError)
46 {
47 AssertPtrReturn(poffError, VINF_SUCCESS);
48 *poffError = 0;
49 }
50 AssertReturn(!(fFlags & ~RTVFS_VALIDATE_UTF8_VALID_MASK), VERR_INVALID_PARAMETER);
51
52 /*
53 * The loop.
54 */
55 char achBuf[1024 + 1];
56 size_t cbUsed = 0;
57 int rc;
58 for (;;)
59 {
60 /*
61 * Fill the buffer
62 */
63 size_t cbRead = 0;
64 rc = RTVfsIoStrmRead(hVfsIos, &achBuf[cbUsed], sizeof(achBuf) - cbUsed - 1, true /*fBlocking*/, &cbRead);
65 if (RT_FAILURE(rc))
66 break;
67 cbUsed += cbRead;
68 if (!cbUsed)
69 {
70 Assert(rc == VINF_EOF);
71 break;
72 }
73 achBuf[sizeof(achBuf) - 1] = '\0';
74
75 /*
76 * Process the data in the buffer, maybe leaving the final chars till
77 * the next round.
78 */
79 const char *pszCur = achBuf;
80 size_t offEnd = rc == VINF_EOF
81 ? cbUsed
82 : cbUsed >= 7
83 ? cbUsed - 7
84 : 0;
85 size_t off;
86 while ((off = (pszCur - &achBuf[0])) < offEnd)
87 {
88 RTUNICP uc;
89 rc = RTStrGetCpEx(&pszCur, &uc);
90 if (RT_FAILURE(rc))
91 break;
92 if (!uc)
93 {
94 if (fFlags & RTVFS_VALIDATE_UTF8_NO_NULL)
95 {
96 rc = VERR_INVALID_UTF8_ENCODING;
97 break;
98 }
99 }
100 else if (uc > 0x10ffff)
101 {
102 if (fFlags & RTVFS_VALIDATE_UTF8_BY_RTC_3629)
103 {
104 rc = VERR_INVALID_UTF8_ENCODING;
105 break;
106 }
107 }
108 }
109
110 if (off < cbUsed)
111 {
112 cbUsed -= off;
113 memmove(achBuf, pszCur, cbUsed);
114 }
115 }
116
117 /*
118 * Set the offset on failure.
119 */
120 if (poffError && RT_FAILURE(rc))
121 {
122 }
123
124 return rc == VINF_EOF ? VINF_SUCCESS : rc;
125}
126
127
128/** Header size. */
129#define READ_ALL_HEADER_SIZE 0x20
130/** The header magic. It's followed by the size (both size_t). */
131#define READ_ALL_HEADER_MAGIC UINT32_C(0x11223355)
132
133RTDECL(int) RTVfsIoStrmReadAll(RTVFSIOSTREAM hVfsIos, void **ppvBuf, size_t *pcbBuf)
134{
135 /*
136 * Try query the object information and in case the stream has a known
137 * size we could use for guidance.
138 */
139 RTFSOBJINFO ObjInfo;
140 int rc = RTVfsIoStrmQueryInfo(hVfsIos, &ObjInfo, RTFSOBJATTRADD_NOTHING);
141 size_t cbAllocated = RT_SUCCESS(rc) && ObjInfo.cbObject > 0 && ObjInfo.cbObject < _1G
142 ? (size_t)ObjInfo.cbObject + 1 : _16K;
143 cbAllocated += READ_ALL_HEADER_SIZE;
144 void *pvBuf = RTMemAlloc(cbAllocated);
145 if (pvBuf)
146 {
147 memset(pvBuf, 0xfe, READ_ALL_HEADER_SIZE);
148 size_t off = 0;
149 for (;;)
150 {
151 /*
152 * Handle buffer growing and detecting the end of it all.
153 */
154 size_t cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
155 if (!cbToRead)
156 {
157 /* The end? */
158 uint8_t bIgn;
159 size_t cbIgn;
160 rc = RTVfsIoStrmRead(hVfsIos, &bIgn, 0, true /*fBlocking*/, &cbIgn);
161 if (rc == VINF_EOF)
162 break;
163
164 /* Grow the buffer. */
165 cbAllocated -= READ_ALL_HEADER_SIZE - 1;
166 cbAllocated = RT_MAX(RT_MIN(cbAllocated, _32M), _1K);
167 cbAllocated = RT_ALIGN_Z(cbAllocated, _4K);
168 cbAllocated += READ_ALL_HEADER_SIZE + 1;
169
170 void *pvNew = RTMemRealloc(pvBuf, cbAllocated);
171 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
172 pvBuf = pvNew;
173
174 cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
175 }
176 Assert(cbToRead < cbAllocated);
177
178 /*
179 * Read.
180 */
181 size_t cbActual;
182 rc = RTVfsIoStrmRead(hVfsIos, (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE + off, cbToRead,
183 true /*fBlocking*/, &cbActual);
184 if (RT_FAILURE(rc))
185 break;
186 Assert(cbActual > 0);
187 Assert(cbActual <= cbToRead);
188 off += cbActual;
189 if (rc == VINF_EOF)
190 break;
191 }
192 Assert(rc != VERR_EOF);
193 if (RT_SUCCESS(rc))
194 {
195 ((size_t *)pvBuf)[0] = READ_ALL_HEADER_MAGIC;
196 ((size_t *)pvBuf)[1] = off;
197 ((uint8_t *)pvBuf)[READ_ALL_HEADER_SIZE + off] = 0;
198
199 *ppvBuf = (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE;
200 *pcbBuf = off;
201 return VINF_SUCCESS;
202 }
203
204 RTMemFree(pvBuf);
205 }
206 else
207 rc = VERR_NO_MEMORY;
208 *ppvBuf = NULL;
209 *pcbBuf = 0;
210 return rc;
211}
212
213
214RTDECL(void) RTVfsIoStrmReadAllFree(void *pvBuf, size_t cbBuf)
215{
216 AssertPtrReturnVoid(pvBuf);
217
218 /* Spool back to the start of the header. */
219 pvBuf = (uint8_t *)pvBuf - READ_ALL_HEADER_SIZE;
220
221 /* Make sure the caller isn't messing with us. Hardcoded, but works. */
222 Assert(((size_t *)pvBuf)[0] == READ_ALL_HEADER_MAGIC);
223 Assert(((size_t *)pvBuf)[1] == cbBuf); RT_NOREF_PV(cbBuf);
224
225 /* Free it. */
226 RTMemFree(pvBuf);
227}
228
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