|
1 | 1 | /****************************************************************************
|
2 | 2 | **
|
3 |
| -** Copyright (C) 2017 Intel Corporation |
| 3 | +** Copyright (C) 2019 Intel Corporation |
4 | 4 | **
|
5 | 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 | 6 | ** of this software and associated documentation files (the "Software"), to deal
|
|
23 | 23 | ****************************************************************************/
|
24 | 24 |
|
25 | 25 | #define _XOPEN_SOURCE 700
|
| 26 | +#define _DARWIN_C_SOURCE 1 /* need MAP_ANON */ |
26 | 27 | #include <QtTest>
|
27 | 28 | #include "cbor.h"
|
28 | 29 | #include <stdio.h>
|
29 | 30 | #include <stdarg.h>
|
30 | 31 |
|
| 32 | +#if defined(Q_OS_UNIX) |
| 33 | +# include <sys/mman.h> |
| 34 | +# include <unistd.h> |
| 35 | +#elif defined(Q_OS_WIN) |
| 36 | +# define WIN32_LEAN_AND_MEAN 1 |
| 37 | +# define NOMINMAX 1 |
| 38 | +# include <windows.h> |
| 39 | +#endif |
| 40 | + |
31 | 41 | Q_DECLARE_METATYPE(CborError)
|
| 42 | + |
32 | 43 | namespace QTest {
|
33 | 44 | template<> char *toString<CborError>(const CborError &err)
|
34 | 45 | {
|
@@ -101,6 +112,95 @@ private slots:
|
101 | 112 | void recursionLimit();
|
102 | 113 | };
|
103 | 114 |
|
| 115 | +struct ParserWrapper |
| 116 | +{ |
| 117 | + void *realdata = nullptr; |
| 118 | + uint8_t *data; |
| 119 | + size_t len; |
| 120 | + CborParser parser; |
| 121 | + CborValue first; |
| 122 | + |
| 123 | + ~ParserWrapper() { freeMemory(); } |
| 124 | + |
| 125 | + CborError init(const QByteArray &ba) |
| 126 | + { |
| 127 | + freeMemory(); |
| 128 | + data = allocateMemory(ba.size()); |
| 129 | + memcpy(data, ba.data(), ba.size()); |
| 130 | + return cbor_parser_init(data, len, 0, &parser, &first); |
| 131 | + } |
| 132 | + |
| 133 | + uint8_t *allocateMemory(size_t); |
| 134 | + void freeMemory(); |
| 135 | + |
| 136 | + static const size_t PageSize = 4096; |
| 137 | + static inline size_t mmapAllocation(size_t n) |
| 138 | + { |
| 139 | + // round up and add one page |
| 140 | + return (n + 2*PageSize) & ~(PageSize - 1); |
| 141 | + } |
| 142 | + static bool shouldUseMmap(); |
| 143 | +}; |
| 144 | + |
| 145 | +bool ParserWrapper::shouldUseMmap() |
| 146 | +{ |
| 147 | + static int v = qEnvironmentVariableIntValue("PARSER_NO_MMAP"); |
| 148 | + return !v; |
| 149 | +} |
| 150 | + |
| 151 | +uint8_t *ParserWrapper::allocateMemory(size_t n) |
| 152 | +{ |
| 153 | + len = n; |
| 154 | + if (shouldUseMmap()) { |
| 155 | + size_t alloc = mmapAllocation(n); |
| 156 | +#if defined(Q_OS_UNIX) |
| 157 | + realdata = mmap(nullptr, alloc, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
| 158 | + Q_ASSERT_X(realdata != MAP_FAILED, "allocateMemory", "mmap failed!"); |
| 159 | + |
| 160 | + // mark last page inaccessible |
| 161 | + uint8_t *ptr = static_cast<uint8_t *>(realdata); |
| 162 | + ptr += alloc - PageSize; |
| 163 | + mprotect(ptr, PageSize, PROT_NONE); |
| 164 | + |
| 165 | + ptr -= n; |
| 166 | + return ptr; |
| 167 | +#elif defined(Q_OS_WIN) |
| 168 | + // ### implement me |
| 169 | + DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE; |
| 170 | + DWORD flProtect = PAGE_READWRITE; |
| 171 | + realdata = VirtualAlloc(nullptr, alloc, flAllocationType, flProtect); |
| 172 | + Q_ASSERT_X(realdata, "allocateMemory", "VirtualAlloc failed!"); |
| 173 | + |
| 174 | + // mark last page inaccessible |
| 175 | + uint8_t *ptr = static_cast<uint8_t *>(realdata); |
| 176 | + ptr += alloc - PageSize; |
| 177 | + VirtualProtect(ptr, PageSize, PAGE_NOACCESS, nullptr); |
| 178 | + |
| 179 | + ptr -= n; |
| 180 | + return ptr; |
| 181 | +#endif |
| 182 | + } |
| 183 | + realdata = malloc(n); |
| 184 | + return static_cast<uint8_t *>(realdata); |
| 185 | +} |
| 186 | + |
| 187 | +void ParserWrapper::freeMemory() |
| 188 | +{ |
| 189 | + if (shouldUseMmap()) { |
| 190 | + if (realdata) { |
| 191 | +#if defined(Q_OS_UNIX) |
| 192 | + size_t alloc = mmapAllocation(len); |
| 193 | + munmap(realdata, alloc); |
| 194 | +#elif defined(Q_OS_WIN) |
| 195 | + VirtualFree(realdata, 0, MEM_RELEASE); |
| 196 | +#endif |
| 197 | + } |
| 198 | + return; |
| 199 | + } |
| 200 | + |
| 201 | + free(realdata); |
| 202 | +} |
| 203 | + |
104 | 204 | static CborError qstring_printf(void *out, const char *fmt, ...)
|
105 | 205 | {
|
106 | 206 | auto str = static_cast<QString *>(out);
|
@@ -1947,12 +2047,11 @@ void tst_Parser::strictValidation()
|
1947 | 2047 | QFETCH(CborError, expectedError);
|
1948 | 2048 |
|
1949 | 2049 | QString decoded;
|
1950 |
| - CborParser parser; |
1951 |
| - CborValue first; |
1952 |
| - CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first); |
| 2050 | + ParserWrapper w; |
| 2051 | + CborError err = w.init(data); |
1953 | 2052 | QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
|
1954 | 2053 |
|
1955 |
| - err = cbor_value_validate(&first, flags); |
| 2054 | + err = cbor_value_validate(&w.first, flags); |
1956 | 2055 | QCOMPARE(err, expectedError);
|
1957 | 2056 | }
|
1958 | 2057 |
|
|
0 commit comments