Skip to content

Commit a57ac0b

Browse files
committed
Update m3d.h
1 parent 30987ea commit a57ac0b

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

src/external/m3d.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ typedef uint8_t M3D_VOXEL;
8989
#define M3D_NUMBONE 4
9090
#endif
9191
#ifndef M3D_BONEMAXLEVEL
92-
#define M3D_BONEMAXLEVEL 8
92+
#define M3D_BONEMAXLEVEL 64
9393
#endif
9494
#ifndef _MSC_VER
9595
#ifndef _inline
@@ -2172,6 +2172,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
21722172
stbi__context s;
21732173
stbi__result_info ri;
21742174

2175+
/* failsafe */
2176+
if(!fn || !*fn) return M3D_UNDEF;
21752177
/* do we have loaded this texture already? */
21762178
for(i = 0; i < model->numtexture; i++)
21772179
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
22462248
{
22472249
#ifdef M3D_PR_INTERP
22482250
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;
22502252

2251-
if(!buff && model->inlined) {
2253+
if(!buff && fn && *fn && model->inlined) {
22522254
for(i = 0; i < model->numinlined; i++)
22532255
if(!strcmp(fn, model->inlined[i].name)) {
22542256
buff = model->inlined[i].data;
@@ -3439,6 +3441,7 @@ memerr: M3D_LOG("Out of memory");
34393441
model->bone[i].numweight = 0;
34403442
model->bone[i].weight = NULL;
34413443
}
3444+
if(i != model->numbone) { M3D_LOG("Truncated bone chunk"); model->numbone = i; model->numskin = 0; model->errcode = M3D_ERR_BONE; }
34423445
/* read skin definitions */
34433446
if(model->numskin) {
34443447
model->skin = (m3ds_t*)M3D_MALLOC(model->numskin * sizeof(m3ds_t));
@@ -3471,6 +3474,7 @@ memerr: M3D_LOG("Out of memory");
34713474
model->skin[i].weight[j] /= w;
34723475
}
34733476
}
3477+
if(i != model->numskin) { M3D_LOG("Truncated skin in bone chunk"); model->numskin = i; model->errcode = M3D_ERR_BONE; }
34743478
}
34753479
} else
34763480
/* material */
@@ -4726,14 +4730,14 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
47264730
unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE < 8 ? 8 : M3D_NUMBONE], *norm = NULL;
47274731
unsigned int i, j, k, l, n, o, len, chunklen, *length;
47284732
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;
47304734
M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
47314735
#ifdef M3D_VERTEXMAX
47324736
M3D_INDEX lastp;
47334737
#endif
47344738
uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
47354739
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;
47374741
m3dcd_t *cd;
47384742
m3dc_t *cmd;
47394743
m3dstr_t *str = NULL;
@@ -5072,10 +5076,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
50725076
for(i = 0; i < model->numskin; i++) {
50735077
if(skinidx[i] == M3D_UNDEF) continue;
50745078
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++) {
50775080
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;
50795082
min_x += sk.data.weight[j];
50805083
}
50815084
if(j > maxbone) maxbone = j;
@@ -5191,6 +5194,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
51915194
if(sa) M3D_FREE(sa);
51925195
if(sd) M3D_FREE(sd);
51935196
if(out) M3D_FREE(out);
5197+
if(opa) free(opa);
51945198
if(h) M3D_FREE(h);
51955199
M3D_LOG("Out of memory");
51965200
model->errcode = M3D_ERR_ALLOC;
@@ -5218,8 +5222,16 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
52185222
if(model->preview.data && model->preview.length) {
52195223
sl = _m3d_safestr(sn, 0);
52205224
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
52215230
ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)20 + strlen(sl));
52225231
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
5232+
#ifdef __GNUC__
5233+
#pragma GCC diagnostic pop
5234+
#endif
52235235
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
52245236
ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl);
52255237
M3D_FREE(sl); sl = NULL;
@@ -5228,6 +5240,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
52285240
M3D_FREE(sn); sn = NULL;
52295241
/* texture map */
52305242
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 */
52315244
ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxtmap * 32) + (uintptr_t)12);
52325245
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
52335246
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
@@ -5846,9 +5859,13 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
58465859
if(skin[i].newidx == last) continue;
58475860
last = skin[i].newidx;
58485861
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; }
58515865
weights[j] = (uint8_t)(skin[i].data.weight[j] * 255);
5866+
if(!weights[j]) { weights[j]++; l--; }
5867+
}
5868+
weights[k] += l;
58525869
switch(nb_s) {
58535870
case 1: weights[0] = 255; break;
58545871
case 2: memcpy(out, weights, 2); out += 2; break;
@@ -5941,7 +5958,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
59415958
}
59425959
/* mesh face */
59435960
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);
59455962
h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen);
59465963
if(!h) goto memerr;
59475964
memcpy((uint8_t*)h + len, "MESH", 4);
@@ -6268,6 +6285,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
62686285
if(skin) M3D_FREE(skin);
62696286
if(str) M3D_FREE(str);
62706287
if(vrtx) M3D_FREE(vrtx);
6288+
if(opa) free(opa);
62716289
if(h) M3D_FREE(h);
62726290
return out;
62736291
}

0 commit comments

Comments
 (0)