@@ -100,11 +100,11 @@ namespace tinyobj {
100100// cube_left | cube_right
101101
102102#ifdef TINYOBJLOADER_USE_DOUBLE
103- // #pragma message "using double"
104- typedef double real_t ;
103+ // #pragma message "using double"
104+ typedef double real_t ;
105105#else
106- // #pragma message "using float"
107- typedef float real_t ;
106+ // #pragma message "using float"
107+ typedef float real_t ;
108108#endif
109109
110110typedef enum {
@@ -119,7 +119,7 @@ typedef enum {
119119} texture_type_t ;
120120
121121typedef struct {
122- texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
122+ texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
123123 real_t sharpness; // -boost (default 1.0?)
124124 real_t brightness; // base_value in -mm option (default 0)
125125 real_t contrast; // gain_value in -mm option (default 1)
@@ -364,7 +364,6 @@ namespace tinyobj {
364364
365365MaterialReader::~MaterialReader () {}
366366
367-
368367struct vertex_index {
369368 int v_idx, vt_idx, vn_idx;
370369 vertex_index () : v_idx(-1 ), vt_idx(-1 ), vn_idx(-1 ) {}
@@ -428,10 +427,27 @@ static std::istream &safeGetline(std::istream &is, std::string &t) {
428427#define IS_NEW_LINE (x ) (((x) == ' \r ' ) || ((x) == ' \n ' ) || ((x) == ' \0 ' ))
429428
430429// Make index zero-base, and also support relative index.
431- static inline int fixIndex (int idx, int n) {
432- if (idx > 0 ) return idx - 1 ;
433- if (idx == 0 ) return 0 ;
434- return n + idx; // negative value = relative
430+ static inline bool fixIndex (int idx, int n, int *ret) {
431+ if (!ret) {
432+ return false ;
433+ }
434+
435+ if (idx > 0 ) {
436+ (*ret) = idx - 1 ;
437+ return true ;
438+ }
439+
440+ if (idx == 0 ) {
441+ // zero is not allowed according to the spec.
442+ return false ;
443+ }
444+
445+ if (idx < 0 ) {
446+ (*ret) = n + idx; // negative value = relative
447+ return true ;
448+ }
449+
450+ return false ; // never reach here.
435451}
436452
437453static inline std::string parseString (const char **token) {
@@ -584,9 +600,9 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
584600 }
585601
586602assemble:
587- *result =
588- (sign == ' + ' ? 1 : - 1 ) *
589- (exponent ? std::ldexp (mantissa * std::pow ( 5.0 , exponent), exponent) : mantissa);
603+ *result = (sign == ' + ' ? 1 : - 1 ) *
604+ (exponent ? std::ldexp (mantissa * std::pow ( 5.0 , exponent), exponent)
605+ : mantissa);
590606 return true ;
591607fail:
592608 return false ;
@@ -603,16 +619,16 @@ static inline real_t parseReal(const char **token, double default_value = 0.0) {
603619}
604620
605621static inline void parseReal2 (real_t *x, real_t *y, const char **token,
606- const double default_x = 0.0 ,
607- const double default_y = 0.0 ) {
622+ const double default_x = 0.0 ,
623+ const double default_y = 0.0 ) {
608624 (*x) = parseReal (token, default_x);
609625 (*y) = parseReal (token, default_y);
610626}
611627
612- static inline void parseReal3 (real_t *x, real_t *y, real_t *z, const char **token,
613- const double default_x = 0.0 ,
614- const double default_y = 0.0 ,
615- const double default_z = 0.0 ) {
628+ static inline void parseReal3 (real_t *x, real_t *y, real_t *z,
629+ const char **token, const double default_x = 0.0 ,
630+ const double default_y = 0.0 ,
631+ const double default_z = 0.0 ) {
616632 (*x) = parseReal (token, default_x);
617633 (*y) = parseReal (token, default_y);
618634 (*z) = parseReal (token, default_z);
@@ -694,37 +710,57 @@ static tag_sizes parseTagTriple(const char **token) {
694710}
695711
696712// Parse triples with index offsets: i, i/j/k, i//k, i/j
697- static vertex_index parseTriple (const char **token, int vsize, int vnsize,
698- int vtsize) {
713+ static bool parseTriple (const char **token, int vsize, int vnsize, int vtsize,
714+ vertex_index *ret) {
715+ if (!ret) {
716+ return false ;
717+ }
718+
699719 vertex_index vi (-1 );
700720
701- vi.v_idx = fixIndex (atoi ((*token)), vsize);
721+ if (!fixIndex (atoi ((*token)), vsize, &(vi.v_idx ))) {
722+ return false ;
723+ }
724+
702725 (*token) += strcspn ((*token), " / \t\r " );
703726 if ((*token)[0 ] != ' /' ) {
704- return vi;
727+ (*ret) = vi;
728+ return true ;
705729 }
706730 (*token)++;
707731
708732 // i//k
709733 if ((*token)[0 ] == ' /' ) {
710734 (*token)++;
711- vi.vn_idx = fixIndex (atoi ((*token)), vnsize);
735+ if (!fixIndex (atoi ((*token)), vnsize, &(vi.vn_idx ))) {
736+ return false ;
737+ }
712738 (*token) += strcspn ((*token), " / \t\r " );
713- return vi;
739+ (*ret) = vi;
740+ return true ;
714741 }
715742
716743 // i/j/k or i/j
717- vi.vt_idx = fixIndex (atoi ((*token)), vtsize);
744+ if (!fixIndex (atoi ((*token)), vtsize, &(vi.vt_idx ))) {
745+ return false ;
746+ }
747+
718748 (*token) += strcspn ((*token), " / \t\r " );
719749 if ((*token)[0 ] != ' /' ) {
720- return vi;
750+ (*ret) = vi;
751+ return true ;
721752 }
722753
723754 // i/j/k
724755 (*token)++; // skip '/'
725- vi.vn_idx = fixIndex (atoi ((*token)), vnsize);
756+ if (!fixIndex (atoi ((*token)), vnsize, &(vi.vn_idx ))) {
757+ return false ;
758+ }
726759 (*token) += strcspn ((*token), " / \t\r " );
727- return vi;
760+
761+ (*ret) = vi;
762+
763+ return true ;
728764}
729765
730766// Parse raw triples: i, i/j/k, i//k, i/j
@@ -813,15 +849,15 @@ static bool ParseTextureNameAndOption(std::string *texname,
813849 } else if ((0 == strncmp (token, " -o" , 2 )) && IS_SPACE ((token[2 ]))) {
814850 token += 3 ;
815851 parseReal3 (&(texopt->origin_offset [0 ]), &(texopt->origin_offset [1 ]),
816- &(texopt->origin_offset [2 ]), &token);
852+ &(texopt->origin_offset [2 ]), &token);
817853 } else if ((0 == strncmp (token, " -s" , 2 )) && IS_SPACE ((token[2 ]))) {
818854 token += 3 ;
819855 parseReal3 (&(texopt->scale [0 ]), &(texopt->scale [1 ]), &(texopt->scale [2 ]),
820- &token, 1.0 , 1.0 , 1.0 );
856+ &token, 1.0 , 1.0 , 1.0 );
821857 } else if ((0 == strncmp (token, " -t" , 2 )) && IS_SPACE ((token[2 ]))) {
822858 token += 3 ;
823859 parseReal3 (&(texopt->turbulence [0 ]), &(texopt->turbulence [1 ]),
824- &(texopt->turbulence [2 ]), &token);
860+ &(texopt->turbulence [2 ]), &token);
825861 } else if ((0 == strncmp (token, " -type" , 5 )) && IS_SPACE ((token[5 ]))) {
826862 token += 5 ;
827863 texopt->type = parseTextureType ((&token), TEXTURE_TYPE_NONE );
@@ -1532,9 +1568,16 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
15321568 face.reserve (3 );
15331569
15341570 while (!IS_NEW_LINE (token[0 ])) {
1535- vertex_index vi = parseTriple (&token, static_cast <int >(v.size () / 3 ),
1536- static_cast <int >(vn.size () / 3 ),
1537- static_cast <int >(vt.size () / 2 ));
1571+ vertex_index vi;
1572+ if (!parseTriple (&token, static_cast <int >(v.size () / 3 ),
1573+ static_cast <int >(vn.size () / 3 ),
1574+ static_cast <int >(vt.size () / 2 ), &vi)) {
1575+ if (err) {
1576+ (*err) = " Failed parse `f' line(e.g. zero value for face index).\n " ;
1577+ }
1578+ return false ;
1579+ }
1580+
15381581 face.push_back (vi);
15391582 size_t n = strspn (token, " \t\r " );
15401583 token += n;
@@ -1622,7 +1665,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
16221665 // flush previous face group.
16231666 bool ret = exportFaceGroupToShape (&shape, faceGroup, tags, material, name,
16241667 triangulate);
1625- (void )ret; // return value not used.
1668+ (void )ret; // return value not used.
16261669
16271670 if (shape.mesh .indices .size () > 0 ) {
16281671 shapes->push_back (shape);
0 commit comments