diff options
Diffstat (limited to 'Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp')
-rw-r--r-- | Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp | 282 |
1 files changed, 199 insertions, 83 deletions
diff --git a/Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp b/Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp index 0cf7a57ee11..3f71e00cb64 100644 --- a/Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp +++ b/Build/source/libs/icu/icu-src/source/tools/toolutil/pkg_genc.cpp @@ -48,6 +48,8 @@ #include "uoptions.h" #include "pkg_genc.h" #include "filetools.h" +#include "charstr.h" +#include "unicode/errorcode.h" #define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) @@ -56,7 +58,15 @@ /* prototypes --------------------------------------------------------------- */ static void -getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename); +getOutFilename( + const char *inFilename, + const char *destdir, + char *outFilename, + int32_t outFilenameCapacity, + char *entryName, + int32_t entryNameCapacity, + const char *newSuffix, + const char *optFilename); static uint32_t write8(FileStream *out, uint8_t byte, uint32_t column); @@ -259,13 +269,21 @@ printAssemblyHeadersToStdErr(void) { } U_CAPI void U_EXPORT2 -writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { +writeAssemblyCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { uint32_t column = MAX_COLUMN; - char entry[64]; - uint32_t buffer[1024]; - char *bufferStr = (char *)buffer; + char entry[96]; + union { + uint32_t uint32s[1024]; + char chars[4096]; + } buffer; FileStream *in, *out; - size_t i, length; + size_t i, length, count; in=T_FileStream_open(filename, "rb"); if(in==NULL) { @@ -273,15 +291,27 @@ writeAssemblyCode(const char *filename, const char *destdir, const char *optEntr exit(U_FILE_ACCESS_ERROR); } - getOutFilename(filename, destdir, bufferStr, entry, ".S", optFilename); - out=T_FileStream_open(bufferStr, "w"); + getOutFilename( + filename, + destdir, + buffer.chars, + sizeof(buffer.chars), + entry, + sizeof(entry), + ".S", + optFilename); + out=T_FileStream_open(buffer.chars, "w"); if(out==NULL) { - fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); + fprintf(stderr, "genccode: unable to open output file %s\n", buffer.chars); exit(U_FILE_ACCESS_ERROR); } if (outFilePath != NULL) { - uprv_strcpy(outFilePath, bufferStr); + if (uprv_strlen(buffer.chars) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + uprv_strcpy(outFilePath, buffer.chars); } #if defined (WINDOWS_WITH_GNUC) && U_PLATFORM != U_PF_CYGWIN @@ -302,34 +332,42 @@ writeAssemblyCode(const char *filename, const char *destdir, const char *optEntr } } - sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header, + count = snprintf( + buffer.chars, sizeof(buffer.chars), + assemblyHeader[assemblyHeaderIndex].header, entry, entry, entry, entry, entry, entry, entry, entry); - T_FileStream_writeLine(out, bufferStr); + if (count >= sizeof(buffer.chars)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + T_FileStream_writeLine(out, buffer.chars); T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine); for(;;) { - length=T_FileStream_read(in, buffer, sizeof(buffer)); + memset(buffer.uint32s, 0, sizeof(buffer.uint32s)); + length=T_FileStream_read(in, buffer.uint32s, sizeof(buffer.uint32s)); if(length==0) { break; } - if (length != sizeof(buffer)) { - /* pad with extra 0's when at the end of the file */ - for(i=0; i < (length % sizeof(uint32_t)); ++i) { - buffer[length+i] = 0; - } - } - for(i=0; i<(length/sizeof(buffer[0])); i++) { - column = write32(out, buffer[i], column); + for(i=0; i<(length/sizeof(buffer.uint32s[0])); i++) { + // TODO: What if the last read sees length not as a multiple of 4? + column = write32(out, buffer.uint32s[i], column); } } T_FileStream_writeLine(out, "\n"); - sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer, + count = snprintf( + buffer.chars, sizeof(buffer.chars), + assemblyHeader[assemblyHeaderIndex].footer, entry, entry, entry, entry, entry, entry, entry, entry); - T_FileStream_writeLine(out, bufferStr); + if (count >= sizeof(buffer.chars)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + T_FileStream_writeLine(out, buffer.chars); if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); @@ -346,11 +384,17 @@ writeAssemblyCode(const char *filename, const char *destdir, const char *optEntr } U_CAPI void U_EXPORT2 -writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) { +writeCCode( + const char *filename, + const char *destdir, + const char *optName, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { uint32_t column = MAX_COLUMN; - char buffer[4096], entry[64]; + char buffer[4096], entry[96]; FileStream *in, *out; - size_t i, length; + size_t i, length, count; in=T_FileStream_open(filename, "rb"); if(in==NULL) { @@ -359,16 +403,35 @@ writeCCode(const char *filename, const char *destdir, const char *optName, const } if(optName != NULL) { /* prepend 'icudt28_' */ - strcpy(entry, optName); - strcat(entry, "_"); + // +2 includes the _ and the NUL + if (uprv_strlen(optName) + 2 > sizeof(entry)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + strcpy(entry, optName); + strcat(entry, "_"); } else { - entry[0] = 0; + entry[0] = 0; } - getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename); + getOutFilename( + filename, + destdir, + buffer, + sizeof(buffer), + entry + uprv_strlen(entry), + sizeof(entry) - uprv_strlen(entry), + ".c", + optFilename); + if (outFilePath != NULL) { + if (uprv_strlen(buffer) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } uprv_strcpy(outFilePath, buffer); } + out=T_FileStream_open(buffer, "w"); if(out==NULL) { fprintf(stderr, "genccode: unable to open output file %s\n", buffer); @@ -396,7 +459,7 @@ writeCCode(const char *filename, const char *destdir, const char *optName, const magic numbers we must still use the initial double. [grhoten 4/24/2003] */ - sprintf(buffer, + count = snprintf(buffer, sizeof(buffer), "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" @@ -408,6 +471,10 @@ writeCCode(const char *filename, const char *destdir, const char *optName, const " const char *bytes; \n" "} %s={ 0.0, \n", entry); + if (count >= sizeof(buffer)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } T_FileStream_writeLine(out, buffer); for(;;) { @@ -423,7 +490,7 @@ writeCCode(const char *filename, const char *destdir, const char *optName, const T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n"); #else /* Function renaming shouldn't be done in data */ - sprintf(buffer, + count = snprintf(buffer, sizeof(buffer), "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" @@ -435,6 +502,10 @@ writeCCode(const char *filename, const char *destdir, const char *optName, const " uint8_t bytes[%ld]; \n" "} %s={ 0.0, {\n", (long)T_FileStream_size(in), entry); + if (count >= sizeof(buffer)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } T_FileStream_writeLine(out, buffer); for(;;) { @@ -588,66 +659,84 @@ write8str(FileStream *out, uint8_t byte, uint32_t column) { #endif static void -getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) { +getOutFilename( + const char *inFilename, + const char *destdir, + char *outFilename, + int32_t outFilenameCapacity, + char *entryName, + int32_t entryNameCapacity, + const char *newSuffix, + const char *optFilename) { const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.'); + icu::CharString outFilenameBuilder; + icu::CharString entryNameBuilder; + icu::ErrorCode status; + /* copy path */ if(destdir!=NULL && *destdir!=0) { - do { - *outFilename++=*destdir++; - } while(*destdir!=0); - if(*(outFilename-1)!=U_FILE_SEP_CHAR) { - *outFilename++=U_FILE_SEP_CHAR; - } - inFilename=basename; + outFilenameBuilder.append(destdir, status); + outFilenameBuilder.ensureEndsWithFileSeparator(status); } else { - while(inFilename<basename) { - *outFilename++=*inFilename++; - } + outFilenameBuilder.append(inFilename, basename - inFilename, status); } + inFilename=basename; if(suffix==NULL) { /* the filename does not have a suffix */ - uprv_strcpy(entryName, inFilename); + entryNameBuilder.append(inFilename, status); if(optFilename != NULL) { - uprv_strcpy(outFilename, optFilename); + outFilenameBuilder.append(optFilename, status); } else { - uprv_strcpy(outFilename, inFilename); + outFilenameBuilder.append(inFilename, status); } - uprv_strcat(outFilename, newSuffix); + outFilenameBuilder.append(newSuffix, status); } else { - char *saveOutFilename = outFilename; + int32_t saveOutFilenameLength = outFilenameBuilder.length(); /* copy basename */ while(inFilename<suffix) { - if(*inFilename=='-') { - /* iSeries cannot have '-' in the .o objects. */ - *outFilename++=*entryName++='_'; - inFilename++; - } - else { - *outFilename++=*entryName++=*inFilename++; - } + // iSeries cannot have '-' in the .o objects. + char c = (*inFilename=='-') ? '_' : *inFilename; + outFilenameBuilder.append(c, status); + entryNameBuilder.append(c, status); + inFilename++; } /* replace '.' by '_' */ - *outFilename++=*entryName++='_'; + outFilenameBuilder.append('_', status); + entryNameBuilder.append('_', status); ++inFilename; /* copy suffix */ - while(*inFilename!=0) { - *outFilename++=*entryName++=*inFilename++; - } - - *entryName=0; + outFilenameBuilder.append(inFilename, status); + entryNameBuilder.append(inFilename, status); if(optFilename != NULL) { - uprv_strcpy(saveOutFilename, optFilename); - uprv_strcat(saveOutFilename, newSuffix); - } else { - /* add ".c" */ - uprv_strcpy(outFilename, newSuffix); + outFilenameBuilder.truncate(saveOutFilenameLength); + outFilenameBuilder.append(optFilename, status); } + // add ".c" + outFilenameBuilder.append(newSuffix, status); } + + if (status.isFailure()) { + fprintf(stderr, "genccode: error building filename or entrypoint\n"); + exit(status.get()); + } + + if (outFilenameBuilder.length() >= outFilenameCapacity) { + fprintf(stderr, "genccode: output filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + + if (entryNameBuilder.length() >= entryNameCapacity) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + + uprv_strcpy(outFilename, outFilenameBuilder.data()); + uprv_strcpy(entryName, entryNameBuilder.data()); } #ifdef CAN_GENERATE_OBJECTS @@ -685,23 +774,30 @@ getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *pBits=32; *pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB); #elif U_PLATFORM_HAS_WIN32_API -/* _M_IA64 should be defined in windows.h */ -# if defined(_M_IA64) - *pCPU=IMAGE_FILE_MACHINE_IA64; - *pBits = 64; -# elif defined(_M_AMD64) -// link.exe does not really care about the .obj machine type and this will -// allow us to build a dll for both ARM & x64 with an amd64 built tool -// ARM is same as x64 except for first 2 bytes of object file - *pCPU = IMAGE_FILE_MACHINE_UNKNOWN; - // *pCPU = IMAGE_FILE_MACHINE_ARMNT; // If we wanted to be explicit - // *pCPU = IMAGE_FILE_MACHINE_AMD64; // We would use one of these names - *pBits = 64; // Doesn't seem to be used for anything interesting? + // Windows always runs in little-endian mode. + *pIsBigEndian = FALSE; + + // Note: The various _M_<arch> macros are predefined by the MSVC compiler based + // on the target compilation architecture. + // https://docs.microsoft.com/cpp/preprocessor/predefined-macros + + // link.exe will link an IMAGE_FILE_MACHINE_UNKNOWN data-only .obj file + // no matter what architecture it is targeting (though other values are + // required to match). Unfortunately, the variable name decoration/mangling + // is slightly different on x86, which means we can't use the UNKNOWN type + // for all architectures though. +# if defined(_M_IX86) + *pCPU = IMAGE_FILE_MACHINE_I386; # else - *pCPU=IMAGE_FILE_MACHINE_I386; // We would use one of these names + *pCPU = IMAGE_FILE_MACHINE_UNKNOWN; +# endif +# if defined(_M_IA64) || defined(_M_AMD64) || defined (_M_ARM64) + *pBits = 64; // Doesn't seem to be used for anything interesting though? +# elif defined(_M_IX86) || defined(_M_ARM) *pBits = 32; +# else +# error "Unknown platform for CAN_GENERATE_OBJECTS." # endif - *pIsBigEndian=FALSE; #else # error "Unknown platform for CAN_GENERATE_OBJECTS." #endif @@ -775,7 +871,14 @@ getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char } U_CAPI void U_EXPORT2 -writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) { +writeObjectCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optMatchArch, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { /* common variables */ char buffer[4096], entry[96]={ 0 }; FileStream *in, *out; @@ -1059,8 +1162,21 @@ writeObjectCode(const char *filename, const char *destdir, const char *optEntryP } size=T_FileStream_size(in); - getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename); + getOutFilename( + filename, + destdir, + buffer, + sizeof(buffer), + entry + entryOffset, + sizeof(entry) - entryOffset, + newSuffix, + optFilename); + if (outFilePath != NULL) { + if (uprv_strlen(buffer) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } uprv_strcpy(outFilePath, buffer); } |