From 4c328bf846a2f0543f06e2bae0c7ec62411d5b4d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 10:39:06 -0400 Subject: [PATCH 1/6] add metachars '\i' and '\f' to regexp for interger and floating point number chars --- src/utils.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/utils.cpp b/src/utils.cpp index bbda22f24c..a27a53e600 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -39,6 +39,10 @@ * '\W' Non-alphanumeric * '\d' Digits, [0-9] * '\D' Non-digits + * '\i' Integer chars, [0-9], '+' and '-' + * '\I' Non-integers + * '\f' Floating point number chars, [0-9], '.', 'e', 'E', '+' and '-' + * '\F' Non-floats * * *NOT* supported: * '[^abc]' Inverted class @@ -307,6 +311,7 @@ extern "C" { enum { UNUSED, DOT, BEGIN, END, QUESTIONMARK, STAR, PLUS, CHAR, CHAR_CLASS, INV_CHAR_CLASS, DIGIT, NOT_DIGIT, + INTEGER, NOT_INTEGER, FLOAT, NOT_FLOAT, ALPHA, NOT_ALPHA, WHITESPACE, NOT_WHITESPACE /*, BRANCH */ }; typedef struct regex_t { @@ -324,6 +329,8 @@ extern "C" { static int matchplus(regex_t p, regex_t *pattern, const char *text); static int matchone(regex_t p, char c); static int matchdigit(char c); + static int matchint(char c); + static int matchfloat(char c); static int matchalpha(char c); static int matchwhitespace(char c); static int matchmetachar(char c, const char *str); @@ -395,6 +402,10 @@ extern "C" { /* Meta-character: */ case 'd': { re_compiled[j].type = DIGIT; } break; case 'D': { re_compiled[j].type = NOT_DIGIT; } break; + case 'i': { re_compiled[j].type = INTEGER; } break; + case 'I': { re_compiled[j].type = NOT_INTEGER; } break; + case 'f': { re_compiled[j].type = FLOAT; } break; + case 'F': { re_compiled[j].type = NOT_FLOAT; } break; case 'w': { re_compiled[j].type = ALPHA; } break; case 'W': { re_compiled[j].type = NOT_ALPHA; } break; case 's': { re_compiled[j].type = WHITESPACE; } break; @@ -467,6 +478,16 @@ extern "C" { return ((c >= '0') && (c <= '9')); } + static int matchint(char c) + { + return (matchdigit(c) || (c == '-') || (c == '+')); + } + + static int matchfloat(char c) + { + return (matchint(c) || (c == '.') || (c == 'e') || (c == 'E')); + } + static int matchalpha(char c) { return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); @@ -502,6 +523,10 @@ extern "C" { switch (str[0]) { case 'd': return matchdigit(c); case 'D': return !matchdigit(c); + case 'i': return matchint(c); + case 'I': return !matchint(c); + case 'f': return matchfloat(c); + case 'F': return !matchfloat(c); case 'w': return matchalphanum(c); case 'W': return !matchalphanum(c); case 's': return matchwhitespace(c); @@ -544,6 +569,10 @@ extern "C" { case INV_CHAR_CLASS: return !matchcharclass(c, (const char *)p.ccl); case DIGIT: return matchdigit(c); case NOT_DIGIT: return !matchdigit(c); + case INTEGER: return matchint(c); + case NOT_INTEGER: return !matchint(c); + case FLOAT: return matchfloat(c); + case NOT_FLOAT: return !matchfloat(c); case ALPHA: return matchalphanum(c); case NOT_ALPHA: return !matchalphanum(c); case WHITESPACE: return matchwhitespace(c); From 8526e7a4cdb16bb29e00e049e62de472eb9ee6de Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 11:14:39 -0400 Subject: [PATCH 2/6] checking return value of ?scanf() calls to detect problems parsing files --- doc/src/Errors_messages.txt | 5 +++++ src/REPLICA/neb.cpp | 23 ++++++++++++--------- src/USER-REAXC/fix_qeq_reax.cpp | 8 +++++--- src/atom.cpp | 36 ++++++++++++++++++++------------- src/atom.h | 5 +++++ src/reader_native.cpp | 32 ++++++++++++++++++++--------- src/reader_xyz.cpp | 6 ++++-- 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/doc/src/Errors_messages.txt b/doc/src/Errors_messages.txt index 1d635ed841..c55d3743ab 100644 --- a/doc/src/Errors_messages.txt +++ b/doc/src/Errors_messages.txt @@ -5890,6 +5890,11 @@ The element names in the ADP file do not match those requested. :dd The element names in the EAM file do not match those requested. :dd +{Incorrect format of ... section in data file} :dt + +Number or type of values per line in the given section of the data file +is not consistent with the requirements for this section. :dd + {Incorrect format in COMB potential file} :dt Incorrect number of words per line in the potential file. :dd diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index 6b68c52dbb..4061ec6541 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -397,28 +397,33 @@ void NEB::readfile(char *file, int flag) open(file); while (1) { eof = fgets(line,MAXLINE,fp); - if (eof == NULL) error->one(FLERR,"Unexpected end of neb file"); + if (eof == NULL) error->one(FLERR,"Unexpected end of NEB file"); start = &line[strspn(line," \t\n\v\f\r")]; if (*start != '\0' && *start != '#') break; } - sscanf(line,"%d",&nlines); + int rv = sscanf(line,"%d",&nlines); + if (rv != 1) nlines = -1; } MPI_Bcast(&nlines,1,MPI_INT,0,uworld); - + if (nlines < 0) + error->universe_all(FLERR,"Incorrectly formatted NEB file"); } else { if (me == 0) { if (ireplica) { open(file); while (1) { eof = fgets(line,MAXLINE,fp); - if (eof == NULL) error->one(FLERR,"Unexpected end of neb file"); + if (eof == NULL) error->one(FLERR,"Unexpected end of NEB file"); start = &line[strspn(line," \t\n\v\f\r")]; if (*start != '\0' && *start != '#') break; } - sscanf(line,"%d",&nlines); + int rv = sscanf(line,"%d",&nlines); + if (rv != 1) nlines = -1; } else nlines = 0; } MPI_Bcast(&nlines,1,MPI_INT,0,world); + if (nlines < 0) + error->all(FLERR,"Incorrectly formatted NEB file"); } char *buffer = new char[CHUNK*MAXLINE]; @@ -442,7 +447,7 @@ void NEB::readfile(char *file, int flag) eofflag = comm->read_lines_from_file_universe(fp,nchunk,MAXLINE,buffer); else eofflag = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); - if (eofflag) error->all(FLERR,"Unexpected end of neb file"); + if (eofflag) error->all(FLERR,"Unexpected end of NEB file"); buf = buffer; next = strchr(buf,'\n'); @@ -451,7 +456,7 @@ void NEB::readfile(char *file, int flag) *next = '\n'; if (nwords != ATTRIBUTE_PERLINE) - error->all(FLERR,"Incorrect atom format in neb file"); + error->all(FLERR,"Incorrect atom format in NEB file"); // loop over lines of atom coords // tokenize the line into values @@ -509,12 +514,12 @@ void NEB::readfile(char *file, int flag) int ntotal; MPI_Allreduce(&ncount,&ntotal,1,MPI_INT,MPI_SUM,uworld); if (ntotal != nreplica*nlines) - error->universe_all(FLERR,"Invalid atom IDs in neb file"); + error->universe_all(FLERR,"Invalid atom IDs in NEB file"); } else { int ntotal; MPI_Allreduce(&ncount,&ntotal,1,MPI_INT,MPI_SUM,world); if (ntotal != nlines) - error->all(FLERR,"Invalid atom IDs in neb file"); + error->all(FLERR,"Invalid atom IDs in NEB file"); } // clean up diff --git a/src/USER-REAXC/fix_qeq_reax.cpp b/src/USER-REAXC/fix_qeq_reax.cpp index faa0632608..6c0da278c2 100644 --- a/src/USER-REAXC/fix_qeq_reax.cpp +++ b/src/USER-REAXC/fix_qeq_reax.cpp @@ -200,7 +200,7 @@ void FixQEqReax::pertype_parameters(char *arg) return; } - int i,itype,ntypes; + int i,itype,ntypes,rv; double v1,v2,v3; FILE *pf; @@ -216,9 +216,11 @@ void FixQEqReax::pertype_parameters(char *arg) error->one(FLERR,"Fix qeq/reax parameter file could not be found"); for (i = 1; i <= ntypes && !feof(pf); i++) { - fscanf(pf,"%d %lg %lg %lg",&itype,&v1,&v2,&v3); + rv = fscanf(pf,"%d %lg %lg %lg",&itype,&v1,&v2,&v3); + if (rv != 4) + error->one(FLERR,"Fix qeq/reax: Incorrect format of param file"); if (itype < 1 || itype > ntypes) - error->one(FLERR,"Fix qeq/reax invalid atom type in param file"); + error->one(FLERR,"Fix qeq/reax: invalid atom type in param file"); chi[itype] = v1; eta[itype] = v2; gamma[itype] = v3; diff --git a/src/atom.cpp b/src/atom.cpp index 1f5d5a80c4..e5a982d620 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -1071,7 +1071,7 @@ void Atom::data_vels(int n, char *buf, tagint id_offset) void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype; + int m,tmp,itype,rv; tagint atom1,atom2; char *next; int newton_bond = force->newton_bond; @@ -1079,8 +1079,10 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2); + rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT, + &tmp,&itype,&atom1,&atom2); + if (rv != 4) + error->one(FLERR,"Incorrect format of Bonds section in data file"); if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1124,7 +1126,7 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype; + int m,tmp,itype,rv; tagint atom1,atom2,atom3; char *next; int newton_bond = force->newton_bond; @@ -1132,8 +1134,10 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3); + rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, + &tmp,&itype,&atom1,&atom2,&atom3); + if (rv != 5) + error->one(FLERR,"Incorrect format of Angles section in data file"); if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1194,7 +1198,7 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype; + int m,tmp,itype,rv; tagint atom1,atom2,atom3,atom4; char *next; int newton_bond = force->newton_bond; @@ -1202,9 +1206,11 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,"%d %d " - TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3,&atom4); + rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT + " " TAGINT_FORMAT " " TAGINT_FORMAT, + &tmp,&itype,&atom1,&atom2,&atom3,&atom4); + if (rv != 6) + error->one(FLERR,"Incorrect format of Dihedrals section in data file"); if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1283,7 +1289,7 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype; + int m,tmp,itype,rv; tagint atom1,atom2,atom3,atom4; char *next; int newton_bond = force->newton_bond; @@ -1291,9 +1297,11 @@ void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,"%d %d " - TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3,&atom4); + rv = sscanf(buf,"%d %d " + TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, + &tmp,&itype,&atom1,&atom2,&atom3,&atom4); + if (rv != 6) + error->one(FLERR,"Incorrect format of Impropers section in data file"); if (id_offset) { atom1 += id_offset; atom2 += id_offset; diff --git a/src/atom.h b/src/atom.h index 5cd9ca819b..81f643c007 100644 --- a/src/atom.h +++ b/src/atom.h @@ -426,6 +426,11 @@ E: Incorrect atom format in data file Number of values per atom line in the data file is not consistent with the atom style. +E: Incorrect format of ... section in data file + +Number or type of values per line in the given section of the data file +is not consistent with the requirements for this section. + E: Invalid atom type in Atoms section of data file Atom types must range from 1 to specified # of types. diff --git a/src/reader_native.cpp b/src/reader_native.cpp index 7c772ab6b8..60b7ecd764 100644 --- a/src/reader_native.cpp +++ b/src/reader_native.cpp @@ -59,8 +59,9 @@ int ReaderNative::read_time(bigint &ntimestep) if (strstr(line,"ITEM: TIMESTEP") != line) error->one(FLERR,"Dump file is incorrectly formatted"); read_lines(1); - sscanf(line,BIGINT_FORMAT,&ntimestep); - + int rv = sscanf(line,BIGINT_FORMAT,&ntimestep); + if (rv != 1) + error->one(FLERR,"Dump file is incorrectly formatted"); return 0; } @@ -73,7 +74,9 @@ void ReaderNative::skip() { read_lines(2); bigint natoms; - sscanf(line,BIGINT_FORMAT,&natoms); + int rv = sscanf(line,BIGINT_FORMAT,&natoms); + if (rv != 1) + error->one(FLERR,"Dump file is incorrectly formatted"); read_lines(5); @@ -110,8 +113,12 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic, int &xflag, int &yflag, int &zflag) { bigint natoms; + int rv; + read_lines(2); - sscanf(line,BIGINT_FORMAT,&natoms); + rv = sscanf(line,BIGINT_FORMAT,&natoms); + if (rv != 1) + error->one(FLERR,"Dump file is incorrectly formatted"); boxinfo = 1; triclinic = 0; @@ -120,14 +127,19 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic, if (line[strlen("ITEM: BOX BOUNDS ")] == 'x') triclinic = 1; read_lines(1); - if (!triclinic) sscanf(line,"%lg %lg",&box[0][0],&box[0][1]); - else sscanf(line,"%lg %lg %lg",&box[0][0],&box[0][1],&box[0][2]); + if (!triclinic) rv = 2 - sscanf(line,"%lg %lg",&box[0][0],&box[0][1]); + else rv = 3 - sscanf(line,"%lg %lg %lg",&box[0][0],&box[0][1],&box[0][2]); + if (rv != 0) error->one(FLERR,"Dump file is incorrectly formatted"); + read_lines(1); - if (!triclinic) sscanf(line,"%lg %lg",&box[1][0],&box[1][1]); - else sscanf(line,"%lg %lg %lg",&box[1][0],&box[1][1],&box[1][2]); + if (!triclinic) rv = 2 - sscanf(line,"%lg %lg",&box[1][0],&box[1][1]); + else rv = 3 - sscanf(line,"%lg %lg %lg",&box[1][0],&box[1][1],&box[1][2]); + if (rv != 0) error->one(FLERR,"Dump file is incorrectly formatted"); + read_lines(1); - if (!triclinic) sscanf(line,"%lg %lg",&box[2][0],&box[2][1]); - else sscanf(line,"%lg %lg %lg",&box[2][0],&box[2][1],&box[2][2]); + if (!triclinic) rv = 2 - sscanf(line,"%lg %lg",&box[2][0],&box[2][1]); + else rv = 3 - sscanf(line,"%lg %lg %lg",&box[2][0],&box[2][1],&box[2][2]); + if (rv != 0) error->one(FLERR,"Dump file is incorrectly formatted"); read_lines(1); diff --git a/src/reader_xyz.cpp b/src/reader_xyz.cpp index 303c25cd7a..040eb9d460 100644 --- a/src/reader_xyz.cpp +++ b/src/reader_xyz.cpp @@ -170,7 +170,7 @@ bigint ReaderXYZ::read_header(double /*box*/[3][3], int &boxinfo, int &/*triclin void ReaderXYZ::read_atoms(int n, int nfield, double **fields) { - int i,m; + int i,m,rv; char *eof; int mytype; double myx, myy, myz; @@ -180,7 +180,9 @@ void ReaderXYZ::read_atoms(int n, int nfield, double **fields) if (eof == NULL) error->one(FLERR,"Unexpected end of dump file"); ++nid; - sscanf(line,"%*s%lg%lg%lg", &myx, &myy, &myz); + rv = sscanf(line,"%*s%lg%lg%lg", &myx, &myy, &myz); + if (rv != 3) + error->one("Dump file is incorrectly formatted"); // XXX: we could insert an element2type translation here // XXX: for now we flag unrecognized types as type 0, From 1de00aaab0baf227c49bb7e7bc33ab5f559416cf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 11:16:41 -0400 Subject: [PATCH 3/6] improve parsing of data file header the header lines are now checked using regular expressions instead of strstr() which allows for stricter checking, but also is more forgiving in terms of extra or different whitespace return value of sscanf() calls is checked and on failure LAMMPS errors out --- src/read_data.cpp | 132 +++++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 38 deletions(-) diff --git a/src/read_data.cpp b/src/read_data.cpp index e70a526c38..989f989269 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -45,6 +45,7 @@ #include "irregular.h" #include "error.h" #include "memory.h" +#include "utils.h" using namespace LAMMPS_NS; @@ -999,74 +1000,115 @@ void ReadData::header(int firstpass) // customize for new header lines // check for triangles before angles so "triangles" not matched as "angles" int extra_flag_value = 0; + int rv; - if (strstr(line,"atoms")) { - sscanf(line,BIGINT_FORMAT,&natoms); + if (utils::strmatch(line,"^\\s*\\d+\\s+atoms\\s")) { + rv = sscanf(line,BIGINT_FORMAT,&natoms); + if (rv != 1) + error->all(FLERR,"Could not parse 'atoms' line in data file header"); if (addflag == NONE) atom->natoms = natoms; else if (firstpass) atom->natoms += natoms; - } else if (strstr(line,"ellipsoids")) { + } else if (utils::strmatch(line,"^\\s*\\d+\\s+ellipsoids\\s")) { if (!avec_ellipsoid) error->all(FLERR,"No ellipsoids allowed with this atom style"); - sscanf(line,BIGINT_FORMAT,&nellipsoids); + rv = sscanf(line,BIGINT_FORMAT,&nellipsoids); + if (rv != 1) + error->all(FLERR,"Could not parse 'ellipsoids' line in data file header"); if (addflag == NONE) atom->nellipsoids = nellipsoids; else if (firstpass) atom->nellipsoids += nellipsoids; - } else if (strstr(line,"lines")) { + } else if (utils::strmatch(line,"^\\s*\\d+\\s+lines\\s")) { if (!avec_line) error->all(FLERR,"No lines allowed with this atom style"); - sscanf(line,BIGINT_FORMAT,&nlines); + rv = sscanf(line,BIGINT_FORMAT,&nlines); + if (rv != 1) + error->all(FLERR,"Could not parse 'lines' line in data file header"); if (addflag == NONE) atom->nlines = nlines; else if (firstpass) atom->nlines += nlines; - } else if (strstr(line,"triangles")) { + } else if (utils::strmatch(line,"^\\s*\\d+\\s+triangles\\s")) { if (!avec_tri) error->all(FLERR,"No triangles allowed with this atom style"); - sscanf(line,BIGINT_FORMAT,&ntris); + rv = sscanf(line,BIGINT_FORMAT,&ntris); + if (rv != 1) + error->all(FLERR,"Could not parse 'triangles' line in data file header"); if (addflag == NONE) atom->ntris = ntris; else if (firstpass) atom->ntris += ntris; - } else if (strstr(line,"bodies")) { + } else if (utils::strmatch(line,"^\\s*\\d+\\s+bodies\\s")) { if (!avec_body) error->all(FLERR,"No bodies allowed with this atom style"); - sscanf(line,BIGINT_FORMAT,&nbodies); + rv = sscanf(line,BIGINT_FORMAT,&nbodies); + if (rv != 1) + error->all(FLERR,"Could not parse 'bodies' line in data file header"); if (addflag == NONE) atom->nbodies = nbodies; else if (firstpass) atom->nbodies += nbodies; - } else if (strstr(line,"bonds")) { - sscanf(line,BIGINT_FORMAT,&nbonds); + } else if (utils::strmatch(line,"^\\s*\\d+\\s+bonds\\s")) { + rv = sscanf(line,BIGINT_FORMAT,&nbonds); + if (rv != 1) + error->all(FLERR,"Could not parse 'bonds' line in data file header"); if (addflag == NONE) atom->nbonds = nbonds; else if (firstpass) atom->nbonds += nbonds; - } else if (strstr(line,"angles")) { - sscanf(line,BIGINT_FORMAT,&nangles); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+angles\\s")) { + rv = sscanf(line,BIGINT_FORMAT,&nangles); + if (rv != 1) + error->all(FLERR,"Could not parse 'angles' line in data file header"); if (addflag == NONE) atom->nangles = nangles; else if (firstpass) atom->nangles += nangles; - } else if (strstr(line,"dihedrals")) { - sscanf(line,BIGINT_FORMAT,&ndihedrals); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+dihedrals\\s")) { + rv = sscanf(line,BIGINT_FORMAT,&ndihedrals); + if (rv != 1) + error->all(FLERR,"Could not parse 'dihedrals' line in data file header"); if (addflag == NONE) atom->ndihedrals = ndihedrals; else if (firstpass) atom->ndihedrals += ndihedrals; - } else if (strstr(line,"impropers")) { - sscanf(line,BIGINT_FORMAT,&nimpropers); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+impropers\\s")) { + rv = sscanf(line,BIGINT_FORMAT,&nimpropers); + if (rv != 1) + error->all(FLERR,"Could not parse 'impropers' line in data file header"); if (addflag == NONE) atom->nimpropers = nimpropers; else if (firstpass) atom->nimpropers += nimpropers; // Atom class type settings are only set by first data file - } else if (strstr(line,"atom types")) { - sscanf(line,"%d",&ntypes); + } else if (utils::strmatch(line,"^\\s*\\d+\\s+atom\\s+types\\s")) { + rv = sscanf(line,"%d",&ntypes); + if (rv != 1) + error->all(FLERR,"Could not parse 'atom types' line " + "in data file header"); if (addflag == NONE) atom->ntypes = ntypes + extra_atom_types; - } else if (strstr(line,"bond types")) { - sscanf(line,"%d",&nbondtypes); + + } else if (utils::strmatch(line,"\\s*\\d+\\s+bond\\s+types\\s")) { + rv = sscanf(line,"%d",&nbondtypes); + if (rv != 1) + error->all(FLERR,"Could not parse 'bond types' line " + "in data file header"); if (addflag == NONE) atom->nbondtypes = nbondtypes + extra_bond_types; - } else if (strstr(line,"angle types")) { - sscanf(line,"%d",&nangletypes); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+angle\\s+types\\s")) { + rv = sscanf(line,"%d",&nangletypes); + if (rv != 1) + error->all(FLERR,"Could not parse 'angle types' line " + "in data file header"); if (addflag == NONE) atom->nangletypes = nangletypes + extra_angle_types; - } else if (strstr(line,"dihedral types")) { - sscanf(line,"%d",&ndihedraltypes); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+dihedral\\s+types\\s")) { + rv = sscanf(line,"%d",&ndihedraltypes); + if (rv != 1) + error->all(FLERR,"Could not parse 'dihedral types' line " + "in data file header"); if (addflag == NONE) atom->ndihedraltypes = ndihedraltypes + extra_dihedral_types; - } else if (strstr(line,"improper types")) { - sscanf(line,"%d",&nimpropertypes); + + } else if (utils::strmatch(line,"^\\s*\\d+\\s+improper\\s+types\\s")) { + rv = sscanf(line,"%d",&nimpropertypes); + if (rv != 1) + error->all(FLERR,"Could not parse 'improper types' line " + "in data file header"); if (addflag == NONE) atom->nimpropertypes = nimpropertypes + extra_improper_types; @@ -1095,15 +1137,27 @@ void ReadData::header(int firstpass) // local copy of box info // so can treat differently for first vs subsequent data files - } else if (strstr(line,"xlo xhi")) { - sscanf(line,"%lg %lg",&boxlo[0],&boxhi[0]); - } else if (strstr(line,"ylo yhi")) { - sscanf(line,"%lg %lg",&boxlo[1],&boxhi[1]); - } else if (strstr(line,"zlo zhi")) { - sscanf(line,"%lg %lg",&boxlo[2],&boxhi[2]); - } else if (strstr(line,"xy xz yz")) { + } else if (utils::strmatch(line,"^\\s*\\f+\\s+\\f+\\s+xlo\\s+xhi\\s")) { + rv = sscanf(line,"%lg %lg",&boxlo[0],&boxhi[0]); + if (rv != 2) + error->all(FLERR,"Could not parse 'xlo xhi' line in data file header"); + + } else if (utils::strmatch(line,"^\\s*\\f+\\s+\\f+\\s+ylo\\s+yhi\\s")) { + rv = sscanf(line,"%lg %lg",&boxlo[1],&boxhi[1]); + if (rv != 2) + error->all(FLERR,"Could not parse 'ylo yhi' line in data file header"); + + } else if (utils::strmatch(line,"^\\s*\\f+\\s+\\f+\\s+zlo\\s+zhi\\s")) { + rv = sscanf(line,"%lg %lg",&boxlo[2],&boxhi[2]); + if (rv != 2) + error->all(FLERR,"Could not parse 'zlo zhi' line in data file header"); + + } else if (utils::strmatch(line,"^\\s*\\f+\\s+\\f+\\s+\\f+" + "\\s+xy\\s+xz\\s+yz\\s")) { triclinic = 1; - sscanf(line,"%lg %lg %lg",&xy,&xz,&yz); + rv = sscanf(line,"%lg %lg %lg",&xy,&xz,&yz); + if (rv != 3) + error->all(FLERR,"Could not parse 'xy xz yz' line in data file header"); } else break; } @@ -1638,7 +1692,7 @@ void ReadData::bonus(bigint nbonus, AtomVec *ptr, const char *type) void ReadData::bodies(int firstpass) { - int m,nchunk,nline,nmax,ninteger,ndouble,nword,ncount,onebody,tmp; + int m,nchunk,nline,nmax,ninteger,ndouble,nword,ncount,onebody,tmp,rv; char *eof; int mapflag = 0; @@ -1666,7 +1720,9 @@ void ReadData::bodies(int firstpass) while (nchunk < nmax && nline <= CHUNK-MAXBODY) { eof = fgets(&buffer[m],MAXLINE,fp); if (eof == NULL) error->one(FLERR,"Unexpected end of data file"); - sscanf(&buffer[m],"%d %d %d",&tmp,&ninteger,&ndouble); + rv = sscanf(&buffer[m],"%d %d %d",&tmp,&ninteger,&ndouble); + if (rv != 3) + error->one(FLERR,"Incorrect format in Bodies section of data file"); m += strlen(&buffer[m]); // read lines one at a time into buffer and count words From d730ef5b19dfe7b14327ddb9a0733f49c04baf4b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 11:31:45 -0400 Subject: [PATCH 4/6] fix typo --- src/reader_xyz.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reader_xyz.cpp b/src/reader_xyz.cpp index 040eb9d460..19f0ff2135 100644 --- a/src/reader_xyz.cpp +++ b/src/reader_xyz.cpp @@ -182,7 +182,7 @@ void ReaderXYZ::read_atoms(int n, int nfield, double **fields) ++nid; rv = sscanf(line,"%*s%lg%lg%lg", &myx, &myy, &myz); if (rv != 3) - error->one("Dump file is incorrectly formatted"); + error->one(FLERR,"Dump file is incorrectly formatted"); // XXX: we could insert an element2type translation here // XXX: for now we flag unrecognized types as type 0, From e72aef2a9621118f7662f53be37a226037669d30 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 12:01:16 -0400 Subject: [PATCH 5/6] more sscanf() return value checking --- src/procmap.cpp | 9 ++++++--- src/universe.cpp | 10 +++++----- src/variable.cpp | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/procmap.cpp b/src/procmap.cpp index 9d1ed83e73..8207b61f4c 100644 --- a/src/procmap.cpp +++ b/src/procmap.cpp @@ -301,7 +301,8 @@ void ProcMap::custom_grid(char *cfile, int nprocs, MPI_Bcast(&n,1,MPI_INT,0,world); MPI_Bcast(line,n,MPI_CHAR,0,world); - sscanf(line,"%d %d %d",&procgrid[0],&procgrid[1],&procgrid[2]); + int rv = sscanf(line,"%d %d %d",&procgrid[0],&procgrid[1],&procgrid[2]); + if (rv != 3) error->all(FLERR,"Processors custom grid file is inconsistent"); int flag = 0; if (procgrid[0]*procgrid[1]*procgrid[2] != nprocs) flag = 1; @@ -320,8 +321,10 @@ void ProcMap::custom_grid(char *cfile, int nprocs, for (int i = 0; i < nprocs; i++) { if (!fgets(line,MAXLINE,fp)) error->one(FLERR,"Unexpected end of custom file"); - sscanf(line,"%d %d %d %d", - &cmap[i][0],&cmap[i][1],&cmap[i][2],&cmap[i][3]); + rv = sscanf(line,"%d %d %d %d", + &cmap[i][0],&cmap[i][1],&cmap[i][2],&cmap[i][3]); + if (rv != 4) + error->one(FLERR,"Processors custom grid file is inconsistent"); } fclose(fp); } diff --git a/src/universe.cpp b/src/universe.cpp index f078590103..dba31f8b76 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -114,19 +114,19 @@ void Universe::reorder(char *style, char *arg) // read nprocs lines // uni2orig = inverse mapping - int me_orig,me_new; - sscanf(line,"%d %d",&me_orig,&me_new); + int me_orig,me_new,rv; + rv = sscanf(line,"%d %d",&me_orig,&me_new); if (me_orig < 0 || me_orig >= nprocs || - me_new < 0 || me_new >= nprocs) + me_new < 0 || me_new >= nprocs || rv != 2) error->one(FLERR,"Invalid entry in -reorder file"); uni2orig[me_new] = me_orig; for (int i = 1; i < nprocs; i++) { if (!fgets(line,MAXLINE,fp)) error->one(FLERR,"Unexpected end of -reorder file"); - sscanf(line,"%d %d",&me_orig,&me_new); + rv = sscanf(line,"%d %d",&me_orig,&me_new); if (me_orig < 0 || me_orig >= nprocs || - me_new < 0 || me_new >= nprocs) + me_new < 0 || me_new >= nprocs || rv != 2) error->one(FLERR,"Invalid entry in -reorder file"); uni2orig[me_new] = me_orig; } diff --git a/src/variable.cpp b/src/variable.cpp index ea7f3044d7..63a425bcf5 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -5162,8 +5162,8 @@ int VarReader::read_peratom() for (i = 0; i < nchunk; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,TAGINT_FORMAT " %lg",&tag,&value); - if (tag <= 0 || tag > map_tag_max) + int rv = sscanf(buf,TAGINT_FORMAT " %lg",&tag,&value); + if (tag <= 0 || tag > map_tag_max || rv != 2) error->one(FLERR,"Invalid atom ID in variable file"); if ((m = atom->map(tag)) >= 0) vstore[m] = value; buf = next + 1; From 276e3b2df10e5f3ea160986f090651182b56aa5d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 19 Jul 2019 14:00:24 -0400 Subject: [PATCH 6/6] update fix tmd input similar to read_data --- src/fix_tmd.cpp | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/fix_tmd.cpp b/src/fix_tmd.cpp index 4cbb244bc0..10315a750d 100644 --- a/src/fix_tmd.cpp +++ b/src/fix_tmd.cpp @@ -30,6 +30,7 @@ #include "force.h" #include "memory.h" #include "error.h" +#include "utils.h" using namespace LAMMPS_NS; using namespace FixConst; @@ -164,7 +165,7 @@ void FixTMD::init() dtv = update->dt; dtf = update->dt * force->ftm2v; - if (strstr(update->integrate_style,"respa")) + if (utils::strmatch(update->integrate_style,"^respa")) step_respa = ((Respa *) update->integrate)->step; } @@ -423,21 +424,27 @@ void FixTMD::readfile(char *file) *next = '\0'; if (firstline) { - if (strstr(bufptr,"xlo xhi")) { + if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+xlo\\s+xhi")) { double lo,hi; - sscanf(bufptr,"%lg %lg",&lo,&hi); + n = sscanf(bufptr,"%lg %lg",&lo,&hi); + if (n != 2) + error->all(FLERR,"Incorrect format in TMD target file"); xprd = hi - lo; bufptr = next + 1; continue; - } else if (strstr(bufptr,"ylo yhi")) { + } else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+ylo\\s+yhi")) { double lo,hi; - sscanf(bufptr,"%lg %lg",&lo,&hi); + n = sscanf(bufptr,"%lg %lg",&lo,&hi); + if (n != 2) + error->all(FLERR,"Incorrect format in TMD target file"); yprd = hi - lo; bufptr = next + 1; continue; - } else if (strstr(bufptr,"zlo zhi")) { + } else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+zlo\\s+zhi")) { double lo,hi; - sscanf(bufptr,"%lg %lg",&lo,&hi); + n = sscanf(bufptr,"%lg %lg",&lo,&hi); + if (n != 2) + error->all(FLERR,"Incorrect format in TMD target file"); zprd = hi - lo; bufptr = next + 1; continue; @@ -455,14 +462,13 @@ void FixTMD::readfile(char *file) } if (imageflag) - n = sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg %d %d %d", - &itag,&x,&y,&z,&ix,&iy,&iz); + n = 7 - sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg %d %d %d", + &itag,&x,&y,&z,&ix,&iy,&iz); else - n = sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg",&itag,&x,&y,&z); + n = 4 - sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg",&itag,&x,&y,&z); - if (n < 0) { - if (me == 0) error->warning(FLERR,"Ignoring empty or incorrectly" - " formatted line in target file"); + if (n != 0) { + error->all(FLERR,"Incorrectly formatted line in TMD target file"); bufptr = next + 1; continue; }