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 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifdef HAVE_EXPAT 14 : 15 : #include "cpl_port.h" 16 : #include "cpl_conv.h" 17 : #include "cpl_string.h" 18 : #include "ogr_expat.h" 19 : 20 : #include <cstddef> 21 : #include <cstdlib> 22 : 23 : #include "cpl_error.h" 24 : 25 : constexpr size_t OGR_EXPAT_MAX_ALLOWED_ALLOC = 10000000; 26 : 27 : static void *OGRExpatMalloc(size_t size) CPL_WARN_UNUSED_RESULT; 28 : static void *OGRExpatRealloc(void *ptr, size_t size) CPL_WARN_UNUSED_RESULT; 29 : 30 : /************************************************************************/ 31 : /* CanAlloc() */ 32 : /************************************************************************/ 33 : 34 75939 : static bool CanAlloc(size_t size) 35 : { 36 75939 : if (size < OGR_EXPAT_MAX_ALLOWED_ALLOC) 37 75939 : return true; 38 : 39 0 : if (CPLTestBool(CPLGetConfigOption("OGR_EXPAT_UNLIMITED_MEM_ALLOC", "NO"))) 40 0 : return true; 41 : 42 0 : CPLError( 43 : CE_Failure, CPLE_OutOfMemory, 44 : "Expat tried to malloc %d bytes. File probably corrupted. " 45 : "This may also happen in case of a very big XML comment, in which case " 46 : "you may define the OGR_EXPAT_UNLIMITED_MEM_ALLOC configuration " 47 : "option to YES to remove that protection.", 48 : static_cast<int>(size)); 49 0 : return false; 50 : } 51 : 52 : /************************************************************************/ 53 : /* OGRExpatMalloc() */ 54 : /************************************************************************/ 55 : 56 74802 : static void *OGRExpatMalloc(size_t size) 57 : { 58 74802 : if (CanAlloc(size)) 59 74802 : return malloc(size); 60 : 61 0 : return nullptr; 62 : } 63 : 64 : /************************************************************************/ 65 : /* OGRExpatRealloc() */ 66 : /************************************************************************/ 67 : 68 : // Caller must replace the pointer with the returned pointer. 69 1137 : static void *OGRExpatRealloc(void *ptr, size_t size) 70 : { 71 1137 : if (CanAlloc(size)) 72 1137 : return realloc(ptr, size); 73 : 74 0 : return nullptr; 75 : } 76 : 77 : /************************************************************************/ 78 : /* FillWINDOWS1252() */ 79 : /************************************************************************/ 80 : 81 0 : static void FillWINDOWS1252(XML_Encoding *info) 82 : { 83 : // Map CP1252 bytes to Unicode values. 84 0 : for (int i = 0; i < 0x80; ++i) 85 0 : info->map[i] = i; 86 : 87 0 : info->map[0x80] = 0x20AC; 88 0 : info->map[0x81] = -1; 89 0 : info->map[0x82] = 0x201A; 90 0 : info->map[0x83] = 0x0192; 91 0 : info->map[0x84] = 0x201E; 92 0 : info->map[0x85] = 0x2026; 93 0 : info->map[0x86] = 0x2020; 94 0 : info->map[0x87] = 0x2021; 95 0 : info->map[0x88] = 0x02C6; 96 0 : info->map[0x89] = 0x2030; 97 0 : info->map[0x8A] = 0x0160; 98 0 : info->map[0x8B] = 0x2039; 99 0 : info->map[0x8C] = 0x0152; 100 0 : info->map[0x8D] = -1; 101 0 : info->map[0x8E] = 0x017D; 102 0 : info->map[0x8F] = -1; 103 0 : info->map[0x90] = -1; 104 0 : info->map[0x91] = 0x2018; 105 0 : info->map[0x92] = 0x2019; 106 0 : info->map[0x93] = 0x201C; 107 0 : info->map[0x94] = 0x201D; 108 0 : info->map[0x95] = 0x2022; 109 0 : info->map[0x96] = 0x2013; 110 0 : info->map[0x97] = 0x2014; 111 0 : info->map[0x98] = 0x02DC; 112 0 : info->map[0x99] = 0x2122; 113 0 : info->map[0x9A] = 0x0161; 114 0 : info->map[0x9B] = 0x203A; 115 0 : info->map[0x9C] = 0x0153; 116 0 : info->map[0x9D] = -1; 117 0 : info->map[0x9E] = 0x017E; 118 0 : info->map[0x9F] = 0x0178; 119 : 120 0 : for (int i = 0xA0; i <= 0xFF; ++i) 121 0 : info->map[i] = i; 122 0 : } 123 : 124 : /************************************************************************/ 125 : /* FillISO885915() */ 126 : /************************************************************************/ 127 : 128 0 : static void FillISO885915(XML_Encoding *info) 129 : { 130 : // Map ISO-8859-15 bytes to Unicode values. 131 : // Generated by generate_encoding_table.c. 132 0 : for (int i = 0x00; i < 0xA4; ++i) 133 0 : info->map[i] = i; 134 0 : info->map[0xA4] = 0x20AC; 135 0 : info->map[0xA5] = 0xA5; 136 0 : info->map[0xA6] = 0x0160; 137 0 : info->map[0xA7] = 0xA7; 138 0 : info->map[0xA8] = 0x0161; 139 0 : for (int i = 0xA9; i < 0xB4; ++i) 140 0 : info->map[i] = i; 141 0 : info->map[0xB4] = 0x017D; 142 0 : for (int i = 0xB5; i < 0xB8; ++i) 143 0 : info->map[i] = i; 144 0 : info->map[0xB8] = 0x017E; 145 0 : for (int i = 0xB9; i < 0xBC; ++i) 146 0 : info->map[i] = i; 147 0 : info->map[0xBC] = 0x0152; 148 0 : info->map[0xBD] = 0x0153; 149 0 : info->map[0xBE] = 0x0178; 150 0 : for (int i = 0xBF; i < 0x100; ++i) 151 0 : info->map[i] = i; 152 0 : } 153 : 154 : /************************************************************************/ 155 : /* OGRExpatUnknownEncodingHandler() */ 156 : /************************************************************************/ 157 : 158 : static int 159 0 : OGRExpatUnknownEncodingHandler(void * /* unused_encodingHandlerData */, 160 : const XML_Char *name, XML_Encoding *info) 161 : { 162 0 : if (EQUAL(name, "WINDOWS-1252")) 163 0 : FillWINDOWS1252(info); 164 0 : else if (EQUAL(name, "ISO-8859-15")) 165 0 : FillISO885915(info); 166 : else 167 : { 168 0 : CPLDebug("OGR", "Unhandled encoding %s", name); 169 0 : return XML_STATUS_ERROR; 170 : } 171 : 172 0 : info->data = nullptr; 173 0 : info->convert = nullptr; 174 0 : info->release = nullptr; 175 : 176 0 : return XML_STATUS_OK; 177 : } 178 : 179 : /************************************************************************/ 180 : /* OGRCreateExpatXMLParser() */ 181 : /************************************************************************/ 182 : 183 1549 : XML_Parser OGRCreateExpatXMLParser() 184 : { 185 : XML_Memory_Handling_Suite memsuite; 186 1549 : memsuite.malloc_fcn = OGRExpatMalloc; 187 1549 : memsuite.realloc_fcn = OGRExpatRealloc; 188 1549 : memsuite.free_fcn = free; 189 1549 : XML_Parser hParser = XML_ParserCreate_MM(nullptr, &memsuite, nullptr); 190 : 191 1549 : XML_SetUnknownEncodingHandler(hParser, OGRExpatUnknownEncodingHandler, 192 : nullptr); 193 : 194 1549 : return hParser; 195 : } 196 : 197 : #endif // HAVE_EXPAT