@@ -89,7 +89,7 @@ typedef uint8_t M3D_VOXEL;
89
89
#define M3D_NUMBONE 4
90
90
#endif
91
91
#ifndef M3D_BONEMAXLEVEL
92
- #define M3D_BONEMAXLEVEL 8
92
+ #define M3D_BONEMAXLEVEL 64
93
93
#endif
94
94
#ifndef _MSC_VER
95
95
#ifndef _inline
@@ -2172,6 +2172,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
2172
2172
stbi__context s ;
2173
2173
stbi__result_info ri ;
2174
2174
2175
+ /* failsafe */
2176
+ if (!fn || !* fn ) return M3D_UNDEF ;
2175
2177
/* do we have loaded this texture already? */
2176
2178
for (i = 0 ; i < model -> numtexture ; i ++ )
2177
2179
if (!strcmp (fn , model -> texture [i ].name )) return i ;
@@ -2246,9 +2248,9 @@ void _m3d_getpr(m3d_t *model, _unused m3dread_t readfilecb, _unused m3dfree_t f
2246
2248
{
2247
2249
#ifdef M3D_PR_INTERP
2248
2250
unsigned int i , len = 0 ;
2249
- unsigned char * buff = readfilecb ? (* readfilecb )(fn , & len ) : NULL ;
2251
+ unsigned char * buff = readfilecb && fn && * fn ? (* readfilecb )(fn , & len ) : NULL ;
2250
2252
2251
- if (!buff && model -> inlined ) {
2253
+ if (!buff && fn && * fn && model -> inlined ) {
2252
2254
for (i = 0 ; i < model -> numinlined ; i ++ )
2253
2255
if (!strcmp (fn , model -> inlined [i ].name )) {
2254
2256
buff = model -> inlined [i ].data ;
@@ -3439,6 +3441,7 @@ memerr: M3D_LOG("Out of memory");
3439
3441
model -> bone [i ].numweight = 0 ;
3440
3442
model -> bone [i ].weight = NULL ;
3441
3443
}
3444
+ if (i != model -> numbone ) { M3D_LOG ("Truncated bone chunk" ); model -> numbone = i ; model -> numskin = 0 ; model -> errcode = M3D_ERR_BONE ; }
3442
3445
/* read skin definitions */
3443
3446
if (model -> numskin ) {
3444
3447
model -> skin = (m3ds_t * )M3D_MALLOC (model -> numskin * sizeof (m3ds_t ));
@@ -3471,6 +3474,7 @@ memerr: M3D_LOG("Out of memory");
3471
3474
model -> skin [i ].weight [j ] /= w ;
3472
3475
}
3473
3476
}
3477
+ if (i != model -> numskin ) { M3D_LOG ("Truncated skin in bone chunk" ); model -> numskin = i ; model -> errcode = M3D_ERR_BONE ; }
3474
3478
}
3475
3479
} else
3476
3480
/* material */
@@ -4726,14 +4730,14 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
4726
4730
unsigned char * out = NULL , * z = NULL , weights [M3D_NUMBONE < 8 ? 8 : M3D_NUMBONE ], * norm = NULL ;
4727
4731
unsigned int i , j , k , l , n , o , len , chunklen , * length ;
4728
4732
int maxvox = 0 , minvox = 0 ;
4729
- M3D_FLOAT scale = (M3D_FLOAT )0.0 , min_x , max_x , min_y , max_y , min_z , max_z ;
4733
+ M3D_FLOAT scale = (M3D_FLOAT )0.0 , min_x , max_x , min_y , max_y , min_z , max_z , mw ;
4730
4734
M3D_INDEX last , * vrtxidx = NULL , * mtrlidx = NULL , * tmapidx = NULL , * skinidx = NULL ;
4731
4735
#ifdef M3D_VERTEXMAX
4732
4736
M3D_INDEX lastp ;
4733
4737
#endif
4734
4738
uint32_t idx , numcmap = 0 , * cmap = NULL , numvrtx = 0 , maxvrtx = 0 , numtmap = 0 , maxtmap = 0 , numproc = 0 ;
4735
4739
uint32_t numskin = 0 , maxskin = 0 , numstr = 0 , maxt = 0 , maxbone = 0 , numgrp = 0 , maxgrp = 0 , * grpidx = NULL ;
4736
- uint8_t * opa ;
4740
+ uint8_t * opa = NULL ;
4737
4741
m3dcd_t * cd ;
4738
4742
m3dc_t * cmd ;
4739
4743
m3dstr_t * str = NULL ;
@@ -5072,10 +5076,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
5072
5076
for (i = 0 ; i < model -> numskin ; i ++ ) {
5073
5077
if (skinidx [i ] == M3D_UNDEF ) continue ;
5074
5078
memset (& sk , 0 , sizeof (m3dssave_t ));
5075
- for (j = 0 , min_x = (M3D_FLOAT )0.0 ; j < M3D_NUMBONE && model -> skin [i ].boneid [j ] != M3D_UNDEF &&
5076
- model -> skin [i ].weight [j ] > (M3D_FLOAT )0.0 ; j ++ ) {
5079
+ for (j = 0 , min_x = (M3D_FLOAT )0.0 ; j < M3D_NUMBONE && model -> skin [i ].boneid [j ] != M3D_UNDEF ; j ++ ) {
5077
5080
sk .data .boneid [j ] = model -> skin [i ].boneid [j ];
5078
- sk .data .weight [j ] = model -> skin [i ].weight [j ];
5081
+ sk .data .weight [j ] = model -> skin [i ].weight [j ] > ( M3D_FLOAT ) 0.0 ? model -> skin [ i ]. weight [ j ] : ( M3D_FLOAT ) 0.01 ;
5079
5082
min_x += sk .data .weight [j ];
5080
5083
}
5081
5084
if (j > maxbone ) maxbone = j ;
@@ -5191,6 +5194,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
5191
5194
if (sa ) M3D_FREE (sa );
5192
5195
if (sd ) M3D_FREE (sd );
5193
5196
if (out ) M3D_FREE (out );
5197
+ if (opa ) free (opa );
5194
5198
if (h ) M3D_FREE (h );
5195
5199
M3D_LOG ("Out of memory" );
5196
5200
model -> errcode = M3D_ERR_ALLOC ;
@@ -5218,8 +5222,16 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
5218
5222
if (model -> preview .data && model -> preview .length ) {
5219
5223
sl = _m3d_safestr (sn , 0 );
5220
5224
if (sl ) {
5225
+ /* gcc thinks that "ptr is used after free", well, gcc is simply wrong. */
5226
+ #ifdef __GNUC__
5227
+ #pragma GCC diagnostic push
5228
+ #pragma GCC diagnostic ignored "-Wuse-after-free"
5229
+ #endif
5221
5230
ptr -= (uintptr_t )out ; len = (unsigned int )((uintptr_t )ptr + (uintptr_t )20 + strlen (sl ));
5222
5231
out = (unsigned char * )M3D_REALLOC (out , len ); ptr += (uintptr_t )out ;
5232
+ #ifdef __GNUC__
5233
+ #pragma GCC diagnostic pop
5234
+ #endif
5223
5235
if (!out ) { setlocale (LC_NUMERIC , ol ); goto memerr ; }
5224
5236
ptr += sprintf (ptr , "Preview\r\n%s.png\r\n\r\n" , sl );
5225
5237
M3D_FREE (sl ); sl = NULL ;
@@ -5228,6 +5240,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
5228
5240
M3D_FREE (sn ); sn = NULL ;
5229
5241
/* texture map */
5230
5242
if (numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD ) && !(flags & M3D_EXP_NOFACE )) {
5243
+ /* interestingly gcc does not complain about "ptr is used after free" here, although the code is 100% the same */
5231
5244
ptr -= (uintptr_t )out ; len = (unsigned int )((uintptr_t )ptr + (uintptr_t )(maxtmap * 32 ) + (uintptr_t )12 );
5232
5245
out = (unsigned char * )M3D_REALLOC (out , len ); ptr += (uintptr_t )out ;
5233
5246
if (!out ) { setlocale (LC_NUMERIC , ol ); goto memerr ; }
@@ -5846,9 +5859,13 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
5846
5859
if (skin [i ].newidx == last ) continue ;
5847
5860
last = skin [i ].newidx ;
5848
5861
memset (& weights , 0 , nb_s );
5849
- for (j = 0 ; j < (uint32_t )nb_s && skin [i ].data .boneid [j ] != M3D_UNDEF &&
5850
- skin [i ].data .weight [j ] > (M3D_FLOAT )0.0 ; j ++ )
5862
+ for (j = k = l = 0 , mw = 0.0 ; j < (uint32_t )nb_s && skin [i ].data .boneid [j ] != M3D_UNDEF &&
5863
+ skin [i ].data .weight [j ] > (M3D_FLOAT )0.0 ; j ++ ) {
5864
+ if (mw < skin [i ].data .weight [j ]) { mw = skin [i ].data .weight [j ]; k = j ; }
5851
5865
weights [j ] = (uint8_t )(skin [i ].data .weight [j ] * 255 );
5866
+ if (!weights [j ]) { weights [j ]++ ; l -- ; }
5867
+ }
5868
+ weights [k ] += l ;
5852
5869
switch (nb_s ) {
5853
5870
case 1 : weights [0 ] = 255 ; break ;
5854
5871
case 2 : memcpy (out , weights , 2 ); out += 2 ; break ;
@@ -5941,7 +5958,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
5941
5958
}
5942
5959
/* mesh face */
5943
5960
if (model -> numface && face && !(flags & M3D_EXP_NOFACE )) {
5944
- chunklen = 8 + si_s + model -> numface * (6 * vi_s + 3 * ti_s + si_s + 1 );
5961
+ chunklen = 8 + si_s + model -> numface * (9 * vi_s + 3 * ti_s + si_s + 1 );
5945
5962
h = (m3dhdr_t * )M3D_REALLOC (h , len + chunklen );
5946
5963
if (!h ) goto memerr ;
5947
5964
memcpy ((uint8_t * )h + len , "MESH" , 4 );
@@ -6268,6 +6285,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
6268
6285
if (skin ) M3D_FREE (skin );
6269
6286
if (str ) M3D_FREE (str );
6270
6287
if (vrtx ) M3D_FREE (vrtx );
6288
+ if (opa ) free (opa );
6271
6289
if (h ) M3D_FREE (h );
6272
6290
return out ;
6273
6291
}
0 commit comments