From da3b05728c716207dffee08364c5cfa84da56e10 Mon Sep 17 00:00:00 2001 From: Garux Date: Tue, 19 Jan 2021 00:56:25 +0300 Subject: [PATCH] use safe string for shaderInfo_t.shader --- tools/quake3/common/stringfixedsize.h | 84 +++++++++++++++++++++++++++ tools/quake3/common/unzip.cpp | 4 +- tools/quake3/q3map2/convert_ase.cpp | 2 +- tools/quake3/q3map2/convert_map.cpp | 2 +- tools/quake3/q3map2/convert_obj.cpp | 2 +- tools/quake3/q3map2/light.cpp | 4 +- tools/quake3/q3map2/map.cpp | 2 +- tools/quake3/q3map2/q3map2.h | 4 +- tools/quake3/q3map2/shaders.cpp | 42 +++++++------- tools/quake3/q3map2/surface.cpp | 4 +- tools/quake3/q3map2/surface_extra.cpp | 2 +- tools/quake3/q3map2/writebsp.cpp | 2 +- 12 files changed, 120 insertions(+), 34 deletions(-) create mode 100644 tools/quake3/common/stringfixedsize.h diff --git a/tools/quake3/common/stringfixedsize.h b/tools/quake3/common/stringfixedsize.h new file mode 100644 index 00000000..b69de45c --- /dev/null +++ b/tools/quake3/common/stringfixedsize.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. + + This file is part of GtkRadiant. + + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined( INCLUDED_STRINGFIXESIZE_H ) +#define INCLUDED_STRINGFIXESIZE_H + +#include "stream/textstream.h" +#include "string/string.h" +#include "cmdlib.h" + + +/// \brief A TextOutputStream which writes to a null terminated fixed lenght char array. +/// Similar to std::stringstream. +template +class StringFixedSize : public TextOutputStream +{ + char m_string[SIZE]; + std::size_t m_length; +public: + StringFixedSize() { + clear(); + } + std::size_t write( const char* buffer, std::size_t length ) override { + if( m_length + length < SIZE ){ + for( auto i = length; i != 0; --i ) + m_string[m_length++] = *buffer++; + strClear( &m_string[m_length] ); + } + else{ + Error( "String '%s%.*s' overflow: length >= %d.", m_string, length, buffer, SIZE ); + } + + return length; + } + + StringFixedSize& operator=( const char* string ){ + clear(); + write( string, strlen( string ) ); + return *this; + } + + operator const char*() const { + return c_str(); + } + + bool empty() const { + return strEmpty( m_string ); + } + const char* c_str() const { + return m_string; + } + void clear() { + strClear( m_string ); + m_length = 0; + } +}; + +template +inline StringFixedSize& operator<<( StringFixedSize& ostream, const T& t ) { + return ostream_write( ostream, t ); +} + +using String64 = StringFixedSize<64>; + + +#endif diff --git a/tools/quake3/common/unzip.cpp b/tools/quake3/common/unzip.cpp index 59c1c102..d941fc68 100644 --- a/tools/quake3/common/unzip.cpp +++ b/tools/quake3/common/unzip.cpp @@ -2976,7 +2976,7 @@ int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r) DUMPBITS(14) s->sub.trees.index = 0; Tracev(("inflate: table sizes ok\n")); - s->mode = BTREE; + s->mode = BTREE; // fall through case BTREE: while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) { @@ -2999,7 +2999,7 @@ int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r) } s->sub.trees.index = 0; Tracev(("inflate: bits tree ok\n")); - s->mode = DTREE; + s->mode = DTREE; // fall through case DTREE: while (t = s->sub.trees.table, s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) diff --git a/tools/quake3/q3map2/convert_ase.cpp b/tools/quake3/q3map2/convert_ase.cpp index 78271d40..a408ad09 100644 --- a/tools/quake3/q3map2/convert_ase.cpp +++ b/tools/quake3/q3map2/convert_ase.cpp @@ -270,7 +270,7 @@ static void ConvertShader( FILE *f, bspShader_t *shader, int shaderNum ){ strcpy( filename, si->shaderImage->filename ); } else{ - sprintf( filename, "%s.tga", si->shader ); + sprintf( filename, "%s.tga", si->shader.c_str() ); } for ( c = filename; *c; c++ ) if ( *c == '/' ) { diff --git a/tools/quake3/q3map2/convert_map.cpp b/tools/quake3/q3map2/convert_map.cpp index 31afa5ca..96bf23d6 100644 --- a/tools/quake3/q3map2/convert_map.cpp +++ b/tools/quake3/q3map2/convert_map.cpp @@ -226,7 +226,7 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, vec3_t origin bspBrushSide_t *side; side_t *buildSide; bspShader_t *shader; - char *texture; + const char *texture; plane_t *buildPlane; vec3_t pts[ 3 ]; diff --git a/tools/quake3/q3map2/convert_obj.cpp b/tools/quake3/q3map2/convert_obj.cpp index 46d8a580..872ccb6d 100644 --- a/tools/quake3/q3map2/convert_obj.cpp +++ b/tools/quake3/q3map2/convert_obj.cpp @@ -170,7 +170,7 @@ static void ConvertShaderToMTL( FILE *f, bspShader_t *shader, int shaderNum ){ strcpy( filename, si->shaderImage->filename ); } else{ - sprintf( filename, "%s.tga", si->shader ); + sprintf( filename, "%s.tga", si->shader.c_str() ); } /* blender hates this, so let's not do it diff --git a/tools/quake3/q3map2/light.cpp b/tools/quake3/q3map2/light.cpp index 5ae91ab7..315dfed3 100644 --- a/tools/quake3/q3map2/light.cpp +++ b/tools/quake3/q3map2/light.cpp @@ -526,14 +526,14 @@ void CreateSurfaceLights( void ){ /* sunlight? */ if ( si->sun != NULL && !nss ) { - Sys_FPrintf( SYS_VRB, "Sun: %s\n", si->shader ); + Sys_FPrintf( SYS_VRB, "Sun: %s\n", si->shader.c_str() ); CreateSunLight( si->sun ); si->sun = NULL; /* FIXME: leak! */ } /* sky light? */ if ( si->skyLightValue > 0.0f ) { - Sys_FPrintf( SYS_VRB, "Sky: %s\n", si->shader ); + Sys_FPrintf( SYS_VRB, "Sky: %s\n", si->shader.c_str() ); CreateSkyLights( si->color, si->skyLightValue, si->skyLightIterations, si->lightFilterRadius, si->lightStyle ); si->skyLightValue = 0.0f; /* FIXME: hack! */ } diff --git a/tools/quake3/q3map2/map.cpp b/tools/quake3/q3map2/map.cpp index 7b521a51..b36408af 100644 --- a/tools/quake3/q3map2/map.cpp +++ b/tools/quake3/q3map2/map.cpp @@ -1797,7 +1797,7 @@ static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){ char shader[ MAX_QPATH ]; sprintf( shader, "textures/%s", value ); celShader = ShaderInfoForShader( shader ); - Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader ); + Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader.c_str() ); } else{ celShader = !strEmpty( globalCelShader ) ? ShaderInfoForShader( globalCelShader ) : NULL; diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 5a35d48f..2e7bd5e7 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -84,6 +84,8 @@ #include "png.h" #include "md4.h" +#include "stringfixedsize.h" + #include #include @@ -694,7 +696,7 @@ implicitMap_t; typedef struct shaderInfo_s { - char shader[ MAX_QPATH ]; + String64 shader; int surfaceFlags; int contentFlags; int compileFlags; diff --git a/tools/quake3/q3map2/shaders.cpp b/tools/quake3/q3map2/shaders.cpp index 15038e9e..51c42e61 100644 --- a/tools/quake3/q3map2/shaders.cpp +++ b/tools/quake3/q3map2/shaders.cpp @@ -392,7 +392,7 @@ void WriteMapShaderFile( void ){ num++; /* print it to the file */ - fprintf( file, "%s%s\n", si->shader, si->shaderText ); + fprintf( file, "%s%s\n", si->shader.c_str(), si->shaderText ); //Sys_Printf( "%s%s\n", si->shader, si->shaderText ); /* FIXME: remove debugging code */ Sys_FPrintf( SYS_VRB, "." ); @@ -515,7 +515,7 @@ shaderInfo_t *CustomShader( shaderInfo_t *si, const char *find, char *replace ){ "\t\trgbGen identity\n" "\t}\n" "}\n", - si->shader ); + si->shader.c_str() ); } /* error check */ @@ -556,8 +556,8 @@ shaderInfo_t *CustomShader( shaderInfo_t *si, const char *find, char *replace ){ } /* clone the existing shader and rename */ - memcpy( csi, si, sizeof( shaderInfo_t ) ); - strcpy( csi->shader, shader ); + *csi = *si; + csi->shader = shader; csi->custom = true; /* store new shader text */ @@ -625,7 +625,8 @@ static shaderInfo_t *AllocShaderInfo( void ){ numShaderInfo++; /* ydnar: clear to 0 first */ - memset( si, 0, sizeof( shaderInfo_t ) ); +// memset( si, 0, sizeof( shaderInfo_t ) ); + new (si) shaderInfo_t{}; // placement new /* set defaults */ ApplySurfaceParm( "default", &si->contentFlags, &si->surfaceFlags, &si->compileFlags ); @@ -763,7 +764,7 @@ static void LoadShaderImages( shaderInfo_t *si ){ if ( si->shaderImage == NULL ) { si->shaderImage = ImageLoad( DEFAULT_IMAGE ); if ( warnImage && !strEqual( si->shader, "noshader" ) ) { - Sys_Warning( "Couldn't find image for shader %s\n", si->shader ); + Sys_Warning( "Couldn't find image for shader %s\n", si->shader.c_str() ); } } @@ -774,7 +775,7 @@ static void LoadShaderImages( shaderInfo_t *si ){ si->normalImage = ImageLoad( si->normalImagePath ); if ( si->normalImage != NULL ) { Sys_FPrintf( SYS_VRB, "Shader %s has\n" - " NM %s\n", si->shader, si->normalImagePath ); + " NM %s\n", si->shader.c_str(), si->normalImagePath ); } } @@ -850,7 +851,7 @@ shaderInfo_t *ShaderInfoForShader( const char *shaderName ){ si = &shaderInfo[ i ]; if ( striEqual( shader, si->shader ) ) { /* check if shader is deprecated */ - if ( deprecationDepth < MAX_SHADER_DEPRECATION_DEPTH && si->deprecateShader && si->deprecateShader[ 0 ] ) { + if ( deprecationDepth < MAX_SHADER_DEPRECATION_DEPTH && !strEmptyOrNull( si->deprecateShader ) ) { /* override name */ strcpy( shader, si->deprecateShader ); StripExtension( shader ); @@ -877,7 +878,7 @@ shaderInfo_t *ShaderInfoForShader( const char *shaderName ){ /* allocate a default shader */ si = AllocShaderInfo(); - strcpy( si->shader, shader ); + si->shader << shader; LoadShaderImages( si ); FinishShader( si ); @@ -963,7 +964,7 @@ void Parse1DMatrixAppend( char *buffer, int x, vec_t *m ){ static void ParseShaderFile( const char *filename ){ int i, val; shaderInfo_t *si; - char *suffix, temp[ 1024 ]; + char temp[ 1024 ]; char shaderText[ 8192 ]; /* ydnar: fixme (make this bigger?) */ @@ -995,13 +996,12 @@ static void ParseShaderFile( const char *filename ){ /* shader name is initial token */ si = AllocShaderInfo(); - strcpy( si->shader, token ); /* ignore ":q3map" suffix */ - suffix = strIstr( si->shader, ":q3map" ); - if ( suffix != NULL ) { - strClear( suffix ); - } + if( striEqualSuffix( token, ":q3map" ) ) + si->shader << StringRange( token, token + strlen( token ) - strlen( ":q3map" ) ); + else + si->shader << token; /* handle { } section */ if ( !GetTokenAppend( shaderText, true ) ) { @@ -1010,7 +1010,7 @@ static void ParseShaderFile( const char *filename ){ if ( !strEqual( token, "{" ) ) { if ( si != NULL ) { Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s\nFile location be: %s\n", - filename, scriptline, token, si->shader, g_strLoadedFileLocation ); + filename, scriptline, token, si->shader.c_str(), g_strLoadedFileLocation ); } else{ Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nFile location be: %s\n", @@ -1178,7 +1178,7 @@ static void ParseShaderFile( const char *filename ){ si->implicitMap = IM_OPAQUE; GetTokenAppend( shaderText, false ); if ( strEqual( token, "-" ) ) { - sprintf( si->implicitImagePath, "%s.tga", si->shader ); + sprintf( si->implicitImagePath, "%s.tga", si->shader.c_str() ); } else{ strcpy( si->implicitImagePath, token ); @@ -1189,7 +1189,7 @@ static void ParseShaderFile( const char *filename ){ si->implicitMap = IM_MASKED; GetTokenAppend( shaderText, false ); if ( strEqual( token, "-" ) ) { - sprintf( si->implicitImagePath, "%s.tga", si->shader ); + sprintf( si->implicitImagePath, "%s.tga", si->shader.c_str() ); } else{ strcpy( si->implicitImagePath, token ); @@ -1200,7 +1200,7 @@ static void ParseShaderFile( const char *filename ){ si->implicitMap = IM_MASKED; GetTokenAppend( shaderText, false ); if ( strEqual( token, "-" ) ) { - sprintf( si->implicitImagePath, "%s.tga", si->shader ); + sprintf( si->implicitImagePath, "%s.tga", si->shader.c_str() ); } else{ strcpy( si->implicitImagePath, token ); @@ -1354,10 +1354,10 @@ static void ParseShaderFile( const char *filename ){ strcpy( temp, si->shader ); /* copy shader */ - memcpy( si, si2, sizeof( *si ) ); + *si = *si2; /* restore name and set to unfinished */ - strcpy( si->shader, temp ); + si->shader = temp; si->shaderWidth = 0; si->shaderHeight = 0; si->finished = false; diff --git a/tools/quake3/q3map2/surface.cpp b/tools/quake3/q3map2/surface.cpp index 51502f99..a0025924 100644 --- a/tools/quake3/q3map2/surface.cpp +++ b/tools/quake3/q3map2/surface.cpp @@ -2518,7 +2518,7 @@ void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out ){ if ( bspDrawIndexes[ numBSPDrawIndexes ] < 0 || bspDrawIndexes[ numBSPDrawIndexes ] >= ds->numVerts ) { Sys_Warning( "%d %s has invalid index %d (%d)\n", numBSPDrawSurfaces, - ds->shaderInfo->shader, + ds->shaderInfo->shader.c_str(), bspDrawIndexes[ numBSPDrawIndexes ], i ); bspDrawIndexes[ numBSPDrawIndexes ] = 0; @@ -3747,7 +3747,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){ Sys_Printf( "\n" ); Sys_Warning( "Potentially bad %s surface (%d: %d, %d)\n %s\n", surfaceTypes[ ds->type ], - numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader ); + numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader.c_str() ); } } diff --git a/tools/quake3/q3map2/surface_extra.cpp b/tools/quake3/q3map2/surface_extra.cpp index dc2a8f41..94234289 100644 --- a/tools/quake3/q3map2/surface_extra.cpp +++ b/tools/quake3/q3map2/surface_extra.cpp @@ -255,7 +255,7 @@ void WriteSurfaceExtraFile( const char *path ){ /* shader */ if ( se->si != NULL ) { - fprintf( sf, "\tshader %s\n", se->si->shader ); + fprintf( sf, "\tshader %s\n", se->si->shader.c_str() ); } /* parent surface number */ diff --git a/tools/quake3/q3map2/writebsp.cpp b/tools/quake3/q3map2/writebsp.cpp index fb6657d5..9fbd42d1 100644 --- a/tools/quake3/q3map2/writebsp.cpp +++ b/tools/quake3/q3map2/writebsp.cpp @@ -98,7 +98,7 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){ /* recursively emit any damage shaders */ if ( !strEmptyOrNull( si->damageShader ) ) { - Sys_FPrintf( SYS_VRB, "Shader %s has damage shader %s\n", si->shader, si->damageShader ); + Sys_FPrintf( SYS_VRB, "Shader %s has damage shader %s\n", si->shader.c_str(), si->damageShader ); EmitShader( si->damageShader, NULL, NULL ); }