Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OGR 4 : * Purpose: Convenience function for parsing with Expat library 5 : * Author: Even Rouault, even dot rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * Permission is hereby granted, free of charge, to any person obtaining a 11 : * copy of this software and associated documentation files (the "Software"), 12 : * to deal in the Software without restriction, including without limitation 13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 : * and/or sell copies of the Software, and to permit persons to whom the 15 : * Software is furnished to do so, subject to the following conditions: 16 : * 17 : * The above copyright notice and this permission notice shall be included 18 : * in all copies or substantial portions of the Software. 19 : * 20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 : * DEALINGS IN THE SOFTWARE. 27 : ****************************************************************************/ 28 : 29 : #ifdef HAVE_EXPAT 30 : 31 : #include "cpl_port.h" 32 : #include "cpl_conv.h" 33 : #include "cpl_string.h" 34 : #include "ogr_expat.h" 35 : 36 : #include <cstddef> 37 : #include <cstdlib> 38 : 39 : #include "cpl_error.h" 40 : 41 : constexpr size_t OGR_EXPAT_MAX_ALLOWED_ALLOC = 10000000; 42 : 43 : static void *OGRExpatMalloc(size_t size) CPL_WARN_UNUSED_RESULT; 44 : static void *OGRExpatRealloc(void *ptr, size_t size) CPL_WARN_UNUSED_RESULT; 45 : 46 : /************************************************************************/ 47 : /* CanAlloc() */ 48 : /************************************************************************/ 49 : 50 74650 : static bool CanAlloc(size_t size) 51 : { 52 74650 : if (size < OGR_EXPAT_MAX_ALLOWED_ALLOC) 53 74650 : return true; 54 : 55 0 : if (CPLTestBool(CPLGetConfigOption("OGR_EXPAT_UNLIMITED_MEM_ALLOC", "NO"))) 56 0 : return true; 57 : 58 0 : CPLError( 59 : CE_Failure, CPLE_OutOfMemory, 60 : "Expat tried to malloc %d bytes. File probably corrupted. " 61 : "This may also happen in case of a very big XML comment, in which case " 62 : "you may define the OGR_EXPAT_UNLIMITED_MEM_ALLOC configuration " 63 : "option to YES to remove that protection.", 64 : static_cast<int>(size)); 65 0 : return false; 66 : } 67 : 68 : /************************************************************************/ 69 : /* OGRExpatMalloc() */ 70 : /************************************************************************/ 71 : 72 73514 : static void *OGRExpatMalloc(size_t size) 73 : { 74 73514 : if (CanAlloc(size)) 75 73514 : return malloc(size); 76 : 77 0 : return nullptr; 78 : } 79 : 80 : /************************************************************************/ 81 : /* OGRExpatRealloc() */ 82 : /************************************************************************/ 83 : 84 : // Caller must replace the pointer with the returned pointer. 85 1136 : static void *OGRExpatRealloc(void *ptr, size_t size) 86 : { 87 1136 : if (CanAlloc(size)) 88 1136 : return realloc(ptr, size); 89 : 90 0 : return nullptr; 91 : } 92 : 93 : /************************************************************************/ 94 : /* FillWINDOWS1252() */ 95 : /************************************************************************/ 96 : 97 0 : static void FillWINDOWS1252(XML_Encoding *info) 98 : { 99 : // Map CP1252 bytes to Unicode values. 100 0 : for (int i = 0; i < 0x80; ++i) 101 0 : info->map[i] = i; 102 : 103 0 : info->map[0x80] = 0x20AC; 104 0 : info->map[0x81] = -1; 105 0 : info->map[0x82] = 0x201A; 106 0 : info->map[0x83] = 0x0192; 107 0 : info->map[0x84] = 0x201E; 108 0 : info->map[0x85] = 0x2026; 109 0 : info->map[0x86] = 0x2020; 110 0 : info->map[0x87] = 0x2021; 111 0 : info->map[0x88] = 0x02C6; 112 0 : info->map[0x89] = 0x2030; 113 0 : info->map[0x8A] = 0x0160; 114 0 : info->map[0x8B] = 0x2039; 115 0 : info->map[0x8C] = 0x0152; 116 0 : info->map[0x8D] = -1; 117 0 : info->map[0x8E] = 0x017D; 118 0 : info->map[0x8F] = -1; 119 0 : info->map[0x90] = -1; 120 0 : info->map[0x91] = 0x2018; 121 0 : info->map[0x92] = 0x2019; 122 0 : info->map[0x93] = 0x201C; 123 0 : info->map[0x94] = 0x201D; 124 0 : info->map[0x95] = 0x2022; 125 0 : info->map[0x96] = 0x2013; 126 0 : info->map[0x97] = 0x2014; 127 0 : info->map[0x98] = 0x02DC; 128 0 : info->map[0x99] = 0x2122; 129 0 : info->map[0x9A] = 0x0161; 130 0 : info->map[0x9B] = 0x203A; 131 0 : info->map[0x9C] = 0x0153; 132 0 : info->map[0x9D] = -1; 133 0 : info->map[0x9E] = 0x017E; 134 0 : info->map[0x9F] = 0x0178; 135 : 136 0 : for (int i = 0xA0; i <= 0xFF; ++i) 137 0 : info->map[i] = i; 138 0 : } 139 : 140 : /************************************************************************/ 141 : /* FillISO885915() */ 142 : /************************************************************************/ 143 : 144 0 : static void FillISO885915(XML_Encoding *info) 145 : { 146 : // Map ISO-8859-15 bytes to Unicode values. 147 : // Generated by generate_encoding_table.c. 148 0 : for (int i = 0x00; i < 0xA4; ++i) 149 0 : info->map[i] = i; 150 0 : info->map[0xA4] = 0x20AC; 151 0 : info->map[0xA5] = 0xA5; 152 0 : info->map[0xA6] = 0x0160; 153 0 : info->map[0xA7] = 0xA7; 154 0 : info->map[0xA8] = 0x0161; 155 0 : for (int i = 0xA9; i < 0xB4; ++i) 156 0 : info->map[i] = i; 157 0 : info->map[0xB4] = 0x017D; 158 0 : for (int i = 0xB5; i < 0xB8; ++i) 159 0 : info->map[i] = i; 160 0 : info->map[0xB8] = 0x017E; 161 0 : for (int i = 0xB9; i < 0xBC; ++i) 162 0 : info->map[i] = i; 163 0 : info->map[0xBC] = 0x0152; 164 0 : info->map[0xBD] = 0x0153; 165 0 : info->map[0xBE] = 0x0178; 166 0 : for (int i = 0xBF; i < 0x100; ++i) 167 0 : info->map[i] = i; 168 0 : } 169 : 170 : /************************************************************************/ 171 : /* OGRExpatUnknownEncodingHandler() */ 172 : /************************************************************************/ 173 : 174 : static int 175 0 : OGRExpatUnknownEncodingHandler(void * /* unused_encodingHandlerData */, 176 : const XML_Char *name, XML_Encoding *info) 177 : { 178 0 : if (EQUAL(name, "WINDOWS-1252")) 179 0 : FillWINDOWS1252(info); 180 0 : else if (EQUAL(name, "ISO-8859-15")) 181 0 : FillISO885915(info); 182 : else 183 : { 184 0 : CPLDebug("OGR", "Unhandled encoding %s", name); 185 0 : return XML_STATUS_ERROR; 186 : } 187 : 188 0 : info->data = nullptr; 189 0 : info->convert = nullptr; 190 0 : info->release = nullptr; 191 : 192 0 : return XML_STATUS_OK; 193 : } 194 : 195 : /************************************************************************/ 196 : /* OGRCreateExpatXMLParser() */ 197 : /************************************************************************/ 198 : 199 1514 : XML_Parser OGRCreateExpatXMLParser() 200 : { 201 : XML_Memory_Handling_Suite memsuite; 202 1514 : memsuite.malloc_fcn = OGRExpatMalloc; 203 1514 : memsuite.realloc_fcn = OGRExpatRealloc; 204 1514 : memsuite.free_fcn = free; 205 1514 : XML_Parser hParser = XML_ParserCreate_MM(nullptr, &memsuite, nullptr); 206 : 207 1514 : XML_SetUnknownEncodingHandler(hParser, OGRExpatUnknownEncodingHandler, 208 : nullptr); 209 : 210 1514 : return hParser; 211 : } 212 : 213 : #endif // HAVE_EXPAT