From db510af5822fb39a9cdd76d72b73cd180682b48f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer <akohlmey@gmail.com> Date: Thu, 6 Sep 2018 11:32:44 -0400 Subject: [PATCH] more fixes for potential buffer overflows by using snprintf() instead of sprintf() --- src/USER-OMP/pair_eam_alloy_omp.cpp | 2 +- src/USER-OMP/pair_eam_fs_omp.cpp | 2 +- src/USER-OMP/pair_tersoff_zbl_omp.cpp | 2 +- src/USER-REAXC/fix_reaxc_bonds.cpp | 4 +- src/USER-REAXC/fix_reaxc_species.cpp | 6 +- src/USER-REAXC/pair_reaxc.cpp | 2 +- src/USER-SMD/fix_smd_integrate_tlsph.cpp | 2 +- src/USER-SMD/fix_smd_integrate_ulsph.cpp | 2 +- .../fix_smd_move_triangulated_surface.cpp | 2 +- src/USER-SMD/fix_smd_wall_surface.cpp | 487 +++++++++--------- 10 files changed, 249 insertions(+), 262 deletions(-) diff --git a/src/USER-OMP/pair_eam_alloy_omp.cpp b/src/USER-OMP/pair_eam_alloy_omp.cpp index bbb3b03b02..78b4735863 100644 --- a/src/USER-OMP/pair_eam_alloy_omp.cpp +++ b/src/USER-OMP/pair_eam_alloy_omp.cpp @@ -126,7 +126,7 @@ void PairEAMAlloyOMP::read_file(char *filename) fptr = force->open_potential(filename); if (fptr == NULL) { char str[128]; - sprintf(str,"Cannot open EAM potential file %s",filename); + snprintf(str,128,"Cannot open EAM potential file %s",filename); error->one(FLERR,str); } } diff --git a/src/USER-OMP/pair_eam_fs_omp.cpp b/src/USER-OMP/pair_eam_fs_omp.cpp index a678c887a0..17fecf9b4f 100644 --- a/src/USER-OMP/pair_eam_fs_omp.cpp +++ b/src/USER-OMP/pair_eam_fs_omp.cpp @@ -126,7 +126,7 @@ void PairEAMFSOMP::read_file(char *filename) fptr = force->open_potential(filename); if (fptr == NULL) { char str[128]; - sprintf(str,"Cannot open EAM potential file %s",filename); + snprintf(str,128,"Cannot open EAM potential file %s",filename); error->one(FLERR,str); } } diff --git a/src/USER-OMP/pair_tersoff_zbl_omp.cpp b/src/USER-OMP/pair_tersoff_zbl_omp.cpp index ce3e6fea75..096a42b1a8 100644 --- a/src/USER-OMP/pair_tersoff_zbl_omp.cpp +++ b/src/USER-OMP/pair_tersoff_zbl_omp.cpp @@ -97,7 +97,7 @@ void PairTersoffZBLOMP::read_file(char *file) fp = force->open_potential(file); if (fp == NULL) { char str[128]; - sprintf(str,"Cannot open Tersoff potential file %s",file); + snprintf(str,128,"Cannot open Tersoff potential file %s",file); error->one(FLERR,str); } } diff --git a/src/USER-REAXC/fix_reaxc_bonds.cpp b/src/USER-REAXC/fix_reaxc_bonds.cpp index fb40b2042e..9dc347826f 100644 --- a/src/USER-REAXC/fix_reaxc_bonds.cpp +++ b/src/USER-REAXC/fix_reaxc_bonds.cpp @@ -62,7 +62,7 @@ FixReaxCBonds::FixReaxCBonds(LAMMPS *lmp, int narg, char **arg) : if (suffix && strcmp(suffix,".gz") == 0) { #ifdef LAMMPS_GZIP char gzip[128]; - sprintf(gzip,"gzip -6 > %s",arg[4]); + snprintf(gzip,128,"gzip -6 > %s",arg[4]); #ifdef _WIN32 fp = _popen(gzip,"wb"); #else @@ -75,7 +75,7 @@ FixReaxCBonds::FixReaxCBonds(LAMMPS *lmp, int narg, char **arg) : if (fp == NULL) { char str[128]; - sprintf(str,"Cannot open fix reax/c/bonds file %s",arg[4]); + snprintf(str,128,"Cannot open fix reax/c/bonds file %s",arg[4]); error->one(FLERR,str); } } diff --git a/src/USER-REAXC/fix_reaxc_species.cpp b/src/USER-REAXC/fix_reaxc_species.cpp index 8ec7f4174f..46426d484a 100644 --- a/src/USER-REAXC/fix_reaxc_species.cpp +++ b/src/USER-REAXC/fix_reaxc_species.cpp @@ -98,9 +98,7 @@ FixReaxCSpecies::FixReaxCSpecies(LAMMPS *lmp, int narg, char **arg) : } if (me == 0 && rene_flag) { - char str[128]; - sprintf(str,"Resetting reneighboring criteria for fix reax/c/species"); - error->warning(FLERR,str); + error->warning(FLERR,"Resetting reneighboring criteria for fix reax/c/species"); } tmparg = NULL; @@ -127,7 +125,7 @@ FixReaxCSpecies::FixReaxCSpecies(LAMMPS *lmp, int narg, char **arg) : if (fp == NULL) { char str[128]; - sprintf(str,"Cannot open fix reax/c/species file %s",arg[6]); + snprintf(str,128,"Cannot open fix reax/c/species file %s",arg[6]); error->one(FLERR,str); } } diff --git a/src/USER-REAXC/pair_reaxc.cpp b/src/USER-REAXC/pair_reaxc.cpp index 378d20952c..85bd8471b4 100644 --- a/src/USER-REAXC/pair_reaxc.cpp +++ b/src/USER-REAXC/pair_reaxc.cpp @@ -301,7 +301,7 @@ void PairReaxC::coeff( int nargs, char **args ) Read_Force_Field(fp, &(system->reax_param), control); else { char str[128]; - sprintf(str,"Cannot open ReaxFF potential file %s",file); + snprintf(str,128,"Cannot open ReaxFF potential file %s",file); error->all(FLERR,str); } diff --git a/src/USER-SMD/fix_smd_integrate_tlsph.cpp b/src/USER-SMD/fix_smd_integrate_tlsph.cpp index 1eae45161f..f931ae94ff 100644 --- a/src/USER-SMD/fix_smd_integrate_tlsph.cpp +++ b/src/USER-SMD/fix_smd_integrate_tlsph.cpp @@ -86,7 +86,7 @@ FixSMDIntegrateTlsph::FixSMDIntegrateTlsph(LAMMPS *lmp, int narg, char **arg) : } } else { char msg[128]; - sprintf(msg, "Illegal keyword for smd/integrate_tlsph: %s\n", arg[iarg]); + snprintf(msg,128, "Illegal keyword for smd/integrate_tlsph: %s\n", arg[iarg]); error->all(FLERR, msg); } diff --git a/src/USER-SMD/fix_smd_integrate_ulsph.cpp b/src/USER-SMD/fix_smd_integrate_ulsph.cpp index 685d6af5a8..6c4705eb96 100644 --- a/src/USER-SMD/fix_smd_integrate_ulsph.cpp +++ b/src/USER-SMD/fix_smd_integrate_ulsph.cpp @@ -119,7 +119,7 @@ FixSMDIntegrateUlsph::FixSMDIntegrateUlsph(LAMMPS *lmp, int narg, char **arg) : } } else { char msg[128]; - sprintf(msg, "Illegal keyword for smd/integrate_ulsph: %s\n", arg[iarg]); + snprintf(msg,128, "Illegal keyword for smd/integrate_ulsph: %s\n", arg[iarg]); error->all(FLERR, msg); } diff --git a/src/USER-SMD/fix_smd_move_triangulated_surface.cpp b/src/USER-SMD/fix_smd_move_triangulated_surface.cpp index b0944f1186..fe8695b23e 100644 --- a/src/USER-SMD/fix_smd_move_triangulated_surface.cpp +++ b/src/USER-SMD/fix_smd_move_triangulated_surface.cpp @@ -200,7 +200,7 @@ FixSMDMoveTriSurf::FixSMDMoveTriSurf(LAMMPS *lmp, int narg, char **arg) : } else { char msg[128]; - sprintf(msg, "Illegal keyword for fix smd/move_tri_surf: %s\n", arg[iarg]); + snprintf(msg,128, "Illegal keyword for fix smd/move_tri_surf: %s\n", arg[iarg]); error->all(FLERR, msg); } diff --git a/src/USER-SMD/fix_smd_wall_surface.cpp b/src/USER-SMD/fix_smd_wall_surface.cpp index 4dd415f53e..a37ba67a80 100644 --- a/src/USER-SMD/fix_smd_wall_surface.cpp +++ b/src/USER-SMD/fix_smd_wall_surface.cpp @@ -223,62 +223,59 @@ int FixSMDWallSurface::count_words(const char *line) { void FixSMDWallSurface::read_triangles(int pass) { - double coord[3]; - - int nlocal_previous = atom->nlocal; - int ilocal = nlocal_previous; - int m; - int me; - - bigint natoms_previous = atom->natoms; - Vector3d *vert; - vert = new Vector3d[3]; - Vector3d normal, center; - - FILE *fp = fopen(filename, "r"); - if (fp == NULL) { - char str[128]; - sprintf(str, "Cannot open file %s", filename); - error->one(FLERR, str); - } - - MPI_Comm_rank(world, &me); - if (me == 0) { - if (screen) { - if (pass == 0) { - printf("\n>>========>>========>>========>>========>>========>>========>>========>>========\n"); - fprintf(screen, " scanning triangle pairs ...\n"); - } else { - fprintf(screen, " reading triangle pairs ...\n"); - } - } - if (logfile) { - if (pass == 0) { - fprintf(logfile, " scanning triangle pairs ...\n"); - } else { - fprintf(logfile, " reading triangle pairs ...\n"); - } - } - } - - char str[128]; - char line[256]; - char *retpointer; - char **values; - int nwords; - - // read STL solid name - retpointer = fgets(line, sizeof(line), fp); - if (retpointer == NULL) { - sprintf(str, "error reading number of triangle pairs"); - error->one(FLERR, str); - } - - nwords = count_words(line); - if (nwords < 1) { - sprintf(str, "first line of file is incorrect"); - error->one(FLERR, str); - } + double coord[3]; + + int nlocal_previous = atom->nlocal; + int ilocal = nlocal_previous; + int m; + int me; + + bigint natoms_previous = atom->natoms; + Vector3d *vert; + vert = new Vector3d[3]; + Vector3d normal, center; + + FILE *fp = fopen(filename, "r"); + if (fp == NULL) { + char str[128]; + snprintf(str,128, "Cannot open file %s", filename); + error->one(FLERR, str); + } + + MPI_Comm_rank(world, &me); + if (me == 0) { + if (screen) { + if (pass == 0) { + printf("\n>>========>>========>>========>>========>>========>>========>>========>>========\n"); + fprintf(screen, " scanning triangle pairs ...\n"); + } else { + fprintf(screen, " reading triangle pairs ...\n"); + } + } + if (logfile) { + if (pass == 0) { + fprintf(logfile, " scanning triangle pairs ...\n"); + } else { + fprintf(logfile, " reading triangle pairs ...\n"); + } + } + } + + char line[256]; + char *retpointer; + char **values; + int nwords; + + // read STL solid name + retpointer = fgets(line, sizeof(line), fp); + if (retpointer == NULL) { + error->one(FLERR,"error reading number of triangle pairs"); + } + + nwords = count_words(line); + if (nwords < 1) { + error->one(FLERR,"first line of file is incorrect"); + } // values = new char*[nwords]; // values[0] = strtok(line, " \t\n\r\f"); @@ -295,211 +292,203 @@ void FixSMDWallSurface::read_triangles(int pass) { // cout << "STL file contains solid body with name: " << values[1] << endl; // } - // iterate over STL facets util end of body is reached - - while (fgets(line, sizeof(line), fp)) { // read a line, should be the facet line - - // evaluate facet line - nwords = count_words(line); - if (nwords != 5) { - //sprintf(str, "found end solid line"); - //error->message(FLERR, str); - break; - } else { - // should be facet line - } - - values = new char*[nwords]; - values[0] = strtok(line, " \t\n\r\f"); - if (values[0] == NULL) - error->all(FLERR, "Incorrect atom format in data file"); - for (m = 1; m < nwords; m++) { - values[m] = strtok(NULL, " \t\n\r\f"); - if (values[m] == NULL) - error->all(FLERR, "Incorrect atom format in data file"); - } - - normal << force->numeric(FLERR, values[2]), force->numeric(FLERR, values[3]), force->numeric(FLERR, values[4]); - //cout << "normal is " << normal << endl; - - delete[] values; - - // read outer loop line - retpointer = fgets(line, sizeof(line), fp); - if (retpointer == NULL) { - sprintf(str, "error reading outer loop"); - error->one(FLERR, str); - } - - nwords = count_words(line); - if (nwords != 2) { - sprintf(str, "error reading outer loop"); - error->one(FLERR, str); - } - - // read vertex lines - - for (int k = 0; k < 3; k++) { - retpointer = fgets(line, sizeof(line), fp); - if (retpointer == NULL) { - sprintf(str, "error reading vertex line"); - error->one(FLERR, str); - } - - nwords = count_words(line); - if (nwords != 4) { - sprintf(str, "error reading vertex line"); - error->one(FLERR, str); - } - - values = new char*[nwords]; - values[0] = strtok(line, " \t\n\r\f"); - if (values[0] == NULL) - error->all(FLERR, "Incorrect vertex line"); - for (m = 1; m < nwords; m++) { - values[m] = strtok(NULL, " \t\n\r\f"); - if (values[m] == NULL) - error->all(FLERR, "Incorrect vertex line"); - } - - vert[k] << force->numeric(FLERR, values[1]), force->numeric(FLERR, values[2]), force->numeric(FLERR, values[3]); - //cout << "vertex is " << vert[k] << endl; - //printf("%s %s %s\n", values[1], values[2], values[3]); - delete[] values; - //exit(1); - - } - - // read end loop line - retpointer = fgets(line, sizeof(line), fp); - if (retpointer == NULL) { - sprintf(str, "error reading endloop"); - error->one(FLERR, str); - } - - nwords = count_words(line); - if (nwords != 1) { - sprintf(str, "error reading endloop"); - error->one(FLERR, str); - } - - // read end facet line - retpointer = fgets(line, sizeof(line), fp); - if (retpointer == NULL) { - sprintf(str, "error reading endfacet"); - error->one(FLERR, str); - } - - nwords = count_words(line); - if (nwords != 1) { - sprintf(str, "error reading endfacet"); - error->one(FLERR, str); - } - - // now we have a normal and three vertices ... proceed with adding triangle - - center = (vert[0] + vert[1] + vert[2]) / 3.0; - - // cout << "center is " << center << endl; - - double r1 = (center - vert[0]).norm(); - double r2 = (center - vert[1]).norm(); - double r3 = (center - vert[2]).norm(); - double r = MAX(r1, r2); - r = MAX(r, r3); - - /* - * if atom/molecule is in my subbox, create it - * ... use x0 to hold triangle normal. - * ... use smd_data_9 to hold the three vertices - * ... use x to hold triangle center - * ... radius is the mmaximal distance from triangle center to all vertices - */ - - // printf("coord: %f %f %f\n", coord[0], coord[1], coord[2]); - // printf("sublo: %f %f %f\n", sublo[0], sublo[1], sublo[2]); - // printf("subhi: %f %f %f\n", subhi[0], subhi[1], subhi[2]); - //printf("ilocal = %d\n", ilocal); - if (center(0) >= sublo[0] && center(0) < subhi[0] && center(1) >= sublo[1] && center(1) < subhi[1] && center(2) >= sublo[2] - && center(2) < subhi[2]) { - //printf("******* KERATIN nlocal=%d ***\n", nlocal); - coord[0] = center(0); - coord[1] = center(1); - coord[2] = center(2); - atom->avec->create_atom(wall_particle_type, coord); - - /* - * need to initialize pointers to atom vec arrays here, because they could have changed - * due to calling grow() in create_atoms() above; - */ - - tagint *mol = atom->molecule; - int *type = atom->type; - double *radius = atom->radius; - double *contact_radius = atom->contact_radius; - double **smd_data_9 = atom->smd_data_9; - double **x0 = atom->x0; - - radius[ilocal] = r; //ilocal; - contact_radius[ilocal] = r; //ilocal; - mol[ilocal] = wall_molecule_id; - type[ilocal] = wall_particle_type; - x0[ilocal][0] = normal(0); - x0[ilocal][1] = normal(1); - x0[ilocal][2] = normal(2); - smd_data_9[ilocal][0] = vert[0](0); - smd_data_9[ilocal][1] = vert[0](1); - smd_data_9[ilocal][2] = vert[0](2); - smd_data_9[ilocal][3] = vert[1](0); - smd_data_9[ilocal][4] = vert[1](1); - smd_data_9[ilocal][5] = vert[1](2); - smd_data_9[ilocal][6] = vert[2](0); - smd_data_9[ilocal][7] = vert[2](1); - smd_data_9[ilocal][8] = vert[2](2); - - ilocal++; - } - - } + // iterate over STL facets util end of body is reached + + while (fgets(line, sizeof(line), fp)) { // read a line, should be the facet line + + // evaluate facet line + nwords = count_words(line); + if (nwords != 5) { + //sprintf(str, "found end solid line"); + //error->message(FLERR, str); + break; + } else { + // should be facet line + } + + values = new char*[nwords]; + values[0] = strtok(line, " \t\n\r\f"); + if (values[0] == NULL) + error->all(FLERR, "Incorrect atom format in data file"); + for (m = 1; m < nwords; m++) { + values[m] = strtok(NULL, " \t\n\r\f"); + if (values[m] == NULL) + error->all(FLERR, "Incorrect atom format in data file"); + } + + normal << force->numeric(FLERR, values[2]), force->numeric(FLERR, values[3]), force->numeric(FLERR, values[4]); + //cout << "normal is " << normal << endl; + + delete[] values; + + // read outer loop line + retpointer = fgets(line, sizeof(line), fp); + if (retpointer == NULL) { + error->one(FLERR, "error reading outer loop"); + } + + nwords = count_words(line); + if (nwords != 2) { + error->one(FLERR,"error reading outer loop"); + } + + // read vertex lines + + for (int k = 0; k < 3; k++) { + retpointer = fgets(line, sizeof(line), fp); + if (retpointer == NULL) { + error->one(FLERR,"error reading vertex line"); + } + + nwords = count_words(line); + if (nwords != 4) { + error->one(FLERR,"error reading vertex line"); + } + + values = new char*[nwords]; + values[0] = strtok(line, " \t\n\r\f"); + if (values[0] == NULL) + error->all(FLERR,"Incorrect vertex line"); + for (m = 1; m < nwords; m++) { + values[m] = strtok(NULL, " \t\n\r\f"); + if (values[m] == NULL) + error->all(FLERR, "Incorrect vertex line"); + } + + vert[k] << force->numeric(FLERR, values[1]), force->numeric(FLERR, values[2]), force->numeric(FLERR, values[3]); + //cout << "vertex is " << vert[k] << endl; + //printf("%s %s %s\n", values[1], values[2], values[3]); + delete[] values; + //exit(1); + + } + + // read end loop line + retpointer = fgets(line, sizeof(line), fp); + if (retpointer == NULL) { + error->one(FLERR, "error reading endloop"); + } + + nwords = count_words(line); + if (nwords != 1) { + error->one(FLERR,"error reading endloop"); + } + + // read end facet line + retpointer = fgets(line, sizeof(line), fp); + if (retpointer == NULL) { + error->one(FLERR,"error reading endfacet"); + } + + nwords = count_words(line); + if (nwords != 1) { + error->one(FLERR,"error reading endfacet"); + } + + // now we have a normal and three vertices ... proceed with adding triangle + + center = (vert[0] + vert[1] + vert[2]) / 3.0; + + // cout << "center is " << center << endl; + + double r1 = (center - vert[0]).norm(); + double r2 = (center - vert[1]).norm(); + double r3 = (center - vert[2]).norm(); + double r = MAX(r1, r2); + r = MAX(r, r3); + + /* + * if atom/molecule is in my subbox, create it + * ... use x0 to hold triangle normal. + * ... use smd_data_9 to hold the three vertices + * ... use x to hold triangle center + * ... radius is the mmaximal distance from triangle center to all vertices + */ + + // printf("coord: %f %f %f\n", coord[0], coord[1], coord[2]); + // printf("sublo: %f %f %f\n", sublo[0], sublo[1], sublo[2]); + // printf("subhi: %f %f %f\n", subhi[0], subhi[1], subhi[2]); + //printf("ilocal = %d\n", ilocal); + if (center(0) >= sublo[0] && center(0) < subhi[0] && center(1) >= sublo[1] && center(1) < subhi[1] && center(2) >= sublo[2] + && center(2) < subhi[2]) { + //printf("******* KERATIN nlocal=%d ***\n", nlocal); + coord[0] = center(0); + coord[1] = center(1); + coord[2] = center(2); + atom->avec->create_atom(wall_particle_type, coord); + + /* + * need to initialize pointers to atom vec arrays here, because they could have changed + * due to calling grow() in create_atoms() above; + */ + + tagint *mol = atom->molecule; + int *type = atom->type; + double *radius = atom->radius; + double *contact_radius = atom->contact_radius; + double **smd_data_9 = atom->smd_data_9; + double **x0 = atom->x0; + + radius[ilocal] = r; //ilocal; + contact_radius[ilocal] = r; //ilocal; + mol[ilocal] = wall_molecule_id; + type[ilocal] = wall_particle_type; + x0[ilocal][0] = normal(0); + x0[ilocal][1] = normal(1); + x0[ilocal][2] = normal(2); + smd_data_9[ilocal][0] = vert[0](0); + smd_data_9[ilocal][1] = vert[0](1); + smd_data_9[ilocal][2] = vert[0](2); + smd_data_9[ilocal][3] = vert[1](0); + smd_data_9[ilocal][4] = vert[1](1); + smd_data_9[ilocal][5] = vert[1](2); + smd_data_9[ilocal][6] = vert[2](0); + smd_data_9[ilocal][7] = vert[2](1); + smd_data_9[ilocal][8] = vert[2](2); + + ilocal++; + } + + } // set new total # of atoms and error check - bigint nblocal = atom->nlocal; - MPI_Allreduce(&nblocal, &atom->natoms, 1, MPI_LMP_BIGINT, MPI_SUM, world); - if (atom->natoms < 0 || atom->natoms >= MAXBIGINT) - error->all(FLERR, "Too many total atoms"); + bigint nblocal = atom->nlocal; + MPI_Allreduce(&nblocal, &atom->natoms, 1, MPI_LMP_BIGINT, MPI_SUM, world); + if (atom->natoms < 0 || atom->natoms >= MAXBIGINT) + error->all(FLERR, "Too many total atoms"); // add IDs for newly created atoms // check that atom IDs are valid - if (atom->tag_enable) - atom->tag_extend(); - atom->tag_check(); + if (atom->tag_enable) + atom->tag_extend(); + atom->tag_check(); // create global mapping of atoms // zero nghost in case are adding new atoms to existing atoms - if (atom->map_style) { - atom->nghost = 0; - atom->map_init(); - atom->map_set(); - } + if (atom->map_style) { + atom->nghost = 0; + atom->map_init(); + atom->map_set(); + } // print status - if (comm->me == 0) { - if (screen) { - printf("... fix smd/wall_surface finished reading triangulated surface\n"); - fprintf(screen, "fix smd/wall_surface created " BIGINT_FORMAT " atoms\n", atom->natoms - natoms_previous); - printf(">>========>>========>>========>>========>>========>>========>>========>>========\n"); - } - if (logfile) { - fprintf(logfile, "... fix smd/wall_surface finished reading triangulated surface\n"); - fprintf(logfile, "fix smd/wall_surface created " BIGINT_FORMAT " atoms\n", atom->natoms - natoms_previous); - fprintf(logfile, ">>========>>========>>========>>========>>========>>========>>========>>========\n"); - } - } - - delete[] vert; - fclose(fp); + if (comm->me == 0) { + if (screen) { + printf("... fix smd/wall_surface finished reading triangulated surface\n"); + fprintf(screen, "fix smd/wall_surface created " BIGINT_FORMAT " atoms\n", atom->natoms - natoms_previous); + printf(">>========>>========>>========>>========>>========>>========>>========>>========\n"); + } + if (logfile) { + fprintf(logfile, "... fix smd/wall_surface finished reading triangulated surface\n"); + fprintf(logfile, "fix smd/wall_surface created " BIGINT_FORMAT " atoms\n", atom->natoms - natoms_previous); + fprintf(logfile, ">>========>>========>>========>>========>>========>>========>>========>>========\n"); + } + } + + delete[] vert; + fclose(fp); } -- GitLab