From 10af959e441d175049eee855540b8e7573a03fea Mon Sep 17 00:00:00 2001
From: "Kurt A. O'Hearn" <ohearnku@msu.edu>
Date: Thu, 18 Nov 2021 21:56:02 -0500
Subject: [PATCH] sPuReMD: add error checks around I/O routines to silence
 warnings regarding disregarded return values.

---
 sPuReMD/src/charges.c   |   6 +-
 sPuReMD/src/ffield.c    | 151 ++++++++++++++++++++++++++++++++++------
 sPuReMD/src/geo_tools.c |  52 +++++++++++---
 sPuReMD/src/restart.c   |  44 ++++++++----
 sPuReMD/src/traj.c      |  14 +++-
 5 files changed, 218 insertions(+), 49 deletions(-)

diff --git a/sPuReMD/src/charges.c b/sPuReMD/src/charges.c
index e3771f81..5a52afdf 100644
--- a/sPuReMD/src/charges.c
+++ b/sPuReMD/src/charges.c
@@ -135,7 +135,11 @@ static TF_Buffer* read_file_to_TF_Buffer( const char* file )
     fseek( f, 0, SEEK_SET );  //same as rewind(f);
 
     data = malloc( fsize );
-    fread( data, fsize, 1, f );
+    if ( fread( data, fsize, 1, f ) != 1 )
+    {
+        fprintf( stderr, "[ERROR] reading Tensorflow model file failed\n" );
+        exit( INVALID_INPUT );
+    }
     fclose( f );
 
     buf = TF_NewBuffer();
diff --git a/sPuReMD/src/ffield.c b/sPuReMD/src/ffield.c
index b611538d..cab5dcac 100644
--- a/sPuReMD/src/ffield.c
+++ b/sPuReMD/src/ffield.c
@@ -50,10 +50,20 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* reading first header comment */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading first header comment\n" );
+            exit( INVALID_INPUT );
+        }
 
         /* line 2 is number of global parameters */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of global parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
         /* reading the number of global parameters */
@@ -81,7 +91,12 @@ void Read_Force_Field( const char * const ffield_file,
         /* see reax_types.h for mapping between l[i] and the lambdas used in ff */
         for ( i = 0; i < n; i++ )
         {
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading global parameters (entry %d)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             val = (real) sstrtod( tmp[0], __FILE__, __LINE__ );
@@ -90,14 +105,24 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* next line is number of atom types and some comments */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of single body parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         n = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         /* 3 lines of comments */
-        fgets( s, MAX_LINE, fp );
-        fgets( s, MAX_LINE, fp );
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL
+                || fgets( s, MAX_LINE, fp ) == NULL
+                || fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading single body comments\n" );
+            exit( INVALID_INPUT );
+        }
 
         if ( system->ffield_params_allocated == FALSE )
         {
@@ -222,7 +247,12 @@ void Read_Force_Field( const char * const ffield_file,
         for ( i = 0; i < reax->num_atom_types; i++ )
         {
             /* line one */
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading single body parameters (entry %d, line 1)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             strncpy( reax->sbp[i].name, tmp[0], sizeof(reax->sbp[i].name) - 1 );
@@ -251,7 +281,12 @@ void Read_Force_Field( const char * const ffield_file,
             reax->sbp[i].nlp_opt = 0.5 * (reax->sbp[i].valency_e - reax->sbp[i].valency);
 
             /* line two */
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading single body parameters (entry %d, line 2)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             val = sstrtod( tmp[0], __FILE__, __LINE__ );
@@ -275,7 +310,12 @@ void Read_Force_Field( const char * const ffield_file,
             //0.1 is to avoid from truncating down!
 
             /* line 3 */
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading single body parameters (entry %d, line 3)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             val = sstrtod( tmp[0], __FILE__, __LINE__ );
@@ -294,7 +334,12 @@ void Read_Force_Field( const char * const ffield_file,
             val = sstrtod( tmp[7], __FILE__, __LINE__ );
 
             /* line 4  */
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading single body parameters (entry %d, line 4)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             val = sstrtod( tmp[0], __FILE__, __LINE__ );
@@ -412,17 +457,32 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* next line is number of two body combination and some comments */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of two body parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         l = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         /* a line of comments */
-        fgets(s, MAX_LINE, fp);
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading two body comments\n" );
+            exit( INVALID_INPUT );
+        }
 
         for ( i = 0; i < l; i++ )
         {
             /* line 1 */
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading two body parameters (entry %d, line 1)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             j = sstrtol( tmp[0], __FILE__, __LINE__ ) - 1;
@@ -458,7 +518,12 @@ void Read_Force_Field( const char * const ffield_file,
                 reax->tbp[k][j].p_ovun1 = val;
 
                 /* line 2 */
-                fgets( s, MAX_LINE, fp );
+                if ( fgets( s, MAX_LINE, fp ) == NULL )
+                {
+                    fprintf( stderr, "[ERROR] reading force field failed\n" \
+                             "  [INFO] reading two body parameters (entry %d, line 2)\n", i );
+                    exit( INVALID_INPUT );
+                }
                 Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
                 val = sstrtod( tmp[0], __FILE__, __LINE__ );
@@ -538,13 +603,23 @@ void Read_Force_Field( const char * const ffield_file,
         /* next line is number of 2-body offdiagonal combinations and some comments */
         /* these are two body off-diagonal terms that are different from the
          * combination rules defined above */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of two body off-diagonal parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         l = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         for ( i = 0; i < l; i++ )
         {
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading two body off-diagonal parameters (entry %d)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             j = sstrtol( tmp[0], __FILE__, __LINE__ ) - 1;
@@ -611,13 +686,23 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* next line is number of 3-body params and some comments */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of three body parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         l = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         for ( i = 0; i < l; i++ )
         {
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading three body parameters (entry %d)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             j = sstrtol( tmp[0], __FILE__, __LINE__ ) - 1;
@@ -687,13 +772,23 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* next line is number of 4-body params and some comments */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of four body parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         l = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         for ( i = 0; i < l; i++ )
         {
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading four body parameters (entry %d)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             j = sstrtol( tmp[0], __FILE__, __LINE__ ) - 1;
@@ -782,13 +877,23 @@ void Read_Force_Field( const char * const ffield_file,
         }
 
         /* next line is number of hydrogen bond params and some comments */
-        fgets( s, MAX_LINE, fp );
+        if ( fgets( s, MAX_LINE, fp ) == NULL )
+        {
+            fprintf( stderr, "[ERROR] reading force field failed\n" \
+                     "  [INFO] reading number of hydrogen bond parameters\n" );
+            exit( INVALID_INPUT );
+        }
         Tokenize( s, &tmp, MAX_TOKEN_LEN );
         l = sstrtol( tmp[0], __FILE__, __LINE__ );
 
         for ( i = 0; i < l; i++ )
         {
-            fgets( s, MAX_LINE, fp );
+            if ( fgets( s, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading force field failed\n" \
+                         "  [INFO] reading hydrogen bond parameters (entry %d)\n", i );
+                exit( INVALID_INPUT );
+            }
             Tokenize( s, &tmp, MAX_TOKEN_LEN );
 
             j = sstrtol( tmp[0], __FILE__, __LINE__ ) - 1;
diff --git a/sPuReMD/src/geo_tools.c b/sPuReMD/src/geo_tools.c
index dfd2c5b4..23ea174f 100644
--- a/sPuReMD/src/geo_tools.c
+++ b/sPuReMD/src/geo_tools.c
@@ -200,9 +200,14 @@ static int Read_Box_Info( reax_system *system, FILE *fp, int geo_format )
             break;
 
         case CUSTOM:
-            fscanf( fp, CUSTOM_BOXGEO_FORMAT,
-                    descriptor, &box_x, &box_y, &box_z,
-                    &alpha, &beta, &gamma );
+            if ( fscanf( fp, CUSTOM_BOXGEO_FORMAT,
+                        descriptor, &box_x, &box_y, &box_z,
+                        &alpha, &beta, &gamma ) != 7 )
+            {
+                fprintf( stderr, "[ERROR] reading geometry file failed\n" \
+                         "  [INFO] reading simulation box info\n" );
+                exit( INVALID_INPUT );
+            }
 
             Setup_Box( box_x, box_y, box_z,
                     alpha, beta, gamma,
@@ -259,11 +264,21 @@ static int Count_Atoms( reax_system *system, FILE *fp, int geo_format )
 
         case CUSTOM:
             /* skip box info */
-            fgets( line, MAX_LINE, fp );
+            if ( fgets( line, MAX_LINE, fp ) == NULL )
+            {
+                fprintf( stderr, "[ERROR] reading geometry file failed\n" \
+                         "  [INFO] reading simulation box info\n" );
+                exit( INVALID_INPUT );
+            }
 
             /* second line contains integer count
              * of the number of atoms */
-            fscanf( fp, " %d", &n );
+            if ( fscanf( fp, " %d", &n ) != 1 )
+            {
+                fprintf( stderr, "[ERROR] reading geometry file failed\n" \
+                         "  [INFO] reading number of atoms\n" );
+                exit( INVALID_INPUT );
+            }
 
             break;
 
@@ -322,8 +337,13 @@ void Read_Geo( const char * const geo_file, reax_system* system, control_params
     top = 0;
     for ( i = 0; i < system->N; ++i )
     {
-        fscanf( geo, CUSTOM_ATOM_FORMAT,
-                &serial, element, name, &x[0], &x[1], &x[2] );
+        if ( fscanf( geo, CUSTOM_ATOM_FORMAT,
+                    &serial, element, name, &x[0], &x[1], &x[2] ) != 6 )
+        {
+            fprintf( stderr, "[ERROR] reading geometry file failed\n" \
+                     "  [INFO] reading atom info (entry %d)\n", i );
+            exit( INVALID_INPUT );
+        }
 
         for ( j = 0; j < sizeof(element) - 1; ++j )
         {
@@ -781,8 +801,13 @@ void Read_BGF( const char * const bgf_file, reax_system* system, control_params
 
         if ( strncmp( tokens[0], "CRYSTX", 6 ) == 0 )
         {
-            sscanf( backup, BGF_CRYSTX_FORMAT, descriptor,
-                    s_a, s_b, s_c, s_alpha, s_beta, s_gamma );
+            if ( sscanf( backup, BGF_CRYSTX_FORMAT, descriptor,
+                        s_a, s_b, s_c, s_alpha, s_beta, s_gamma ) != 7 )
+            {
+                fprintf( stderr, "[ERROR] reading geometry file failed\n" \
+                         "  [INFO] reading simulation box info\n" );
+                exit( INVALID_INPUT );
+            }
 
             /* compute full volume tensor from the angles */
             Setup_Box( sstrtod( s_a, __FILE__, __LINE__ ),
@@ -849,9 +874,14 @@ void Read_BGF( const char * const bgf_file, reax_system* system, control_params
             strncpy( charge, backup + 72, sizeof(charge) - 1 );
             charge[sizeof(charge) - 1] = '\0';
 
-//            sscanf( backup, BGF_ATOM_FORMAT, descriptor, serial, atom_name,
+//            if ( sscanf( backup, BGF_ATOM_FORMAT, descriptor, serial, atom_name,
 //                    res_name, &chain_id, res_seq, s_x, s_y, s_z, element,
-//                    occupancy, temp_factor, charge );
+//                    occupancy, temp_factor, charge ) != 13 )
+//            {
+//                fprintf( stderr, "[ERROR] reading geometry file failed\n" );
+//                fprintf( stderr, "  [INFO] reading atom info (entry %d)\n", i );
+//                exit( INVALID_INPUT );
+//            }
 
             /* add to mapping */
             bgf_serial = sstrtod( serial, __FILE__, __LINE__ );
diff --git a/sPuReMD/src/restart.c b/sPuReMD/src/restart.c
index 037d2870..c7bcda42 100644
--- a/sPuReMD/src/restart.c
+++ b/sPuReMD/src/restart.c
@@ -84,7 +84,12 @@ void Read_Binary_Restart( const char * const fname, reax_system *system,
     fres = sfopen( fname, "rb", __FILE__, __LINE__ );
 
     /* parse header of restart file */
-    fread( &res_header, sizeof(restart_header), 1, fres );
+    if ( fread( &res_header, sizeof(restart_header), 1, fres ) != 1 )
+    {
+        fprintf( stderr, "[ERROR] reading restart file failed\n" \
+                "  [INFO] reading header info\n" );
+        exit( INVALID_INPUT );
+    }
 
     data->prev_steps = res_header.step;
     data->therm.T = res_header.T;
@@ -122,7 +127,12 @@ void Read_Binary_Restart( const char * const fname, reax_system *system,
 
     for ( i = 0; i < system->N; ++i )
     {
-        fread( &res_data, sizeof(restart_atom), 1, fres);
+        if ( fread( &res_data, sizeof(restart_atom), 1, fres ) != 1 )
+        {
+            fprintf( stderr, "[ERROR] reading restart file failed\n" \
+                    "  [INFO] reading atom info (%d entry)\n", i );
+            exit( INVALID_INPUT );
+        }
 
         workspace->orig_id[i] = res_data.orig_id;
         workspace->map_serials[res_data.orig_id] = i;
@@ -195,12 +205,17 @@ void Read_ASCII_Restart( const char * const fname, reax_system *system,
     fres = sfopen( fname, "r", __FILE__, __LINE__ );
 
     /* parse header of restart file */
-    fscanf( fres, READ_RESTART_HEADER,
-            &data->prev_steps, &n, &data->therm.T, &data->therm.xi,
-            &data->therm.v_xi, &data->therm.v_xi_old, &data->therm.G_xi,
-            &system->box.box[0][0], &system->box.box[0][1], &system->box.box[0][2],
-            &system->box.box[1][0], &system->box.box[1][1], &system->box.box[1][2],
-            &system->box.box[2][0], &system->box.box[2][1], &system->box.box[2][2]);
+    if ( fscanf( fres, READ_RESTART_HEADER,
+                &data->prev_steps, &n, &data->therm.T, &data->therm.xi,
+                &data->therm.v_xi, &data->therm.v_xi_old, &data->therm.G_xi,
+                &system->box.box[0][0], &system->box.box[0][1], &system->box.box[0][2],
+                &system->box.box[1][0], &system->box.box[1][1], &system->box.box[1][2],
+                &system->box.box[2][0], &system->box.box[2][1], &system->box.box[2][2] ) != 16 )
+    {
+        fprintf( stderr, "[ERROR] reading restart file failed\n" \
+                 "  [INFO] reading header info\n" );
+        exit( INVALID_INPUT );
+    }
 
     rvec_MakeZero( system->box.min );
     Make_Consistent( &system->box );
@@ -231,10 +246,15 @@ void Read_ASCII_Restart( const char * const fname, reax_system *system,
     for ( i = 0; i < system->N; ++i )
     {
         p_atom = &system->atoms[i];
-        fscanf( fres, READ_RESTART_LINE,
-                &workspace->orig_id[i], &p_atom->type, p_atom->name,
-                &p_atom->x[0], &p_atom->x[1], &p_atom->x[2],
-                &p_atom->v[0], &p_atom->v[1], &p_atom->v[2] );
+        if ( fscanf( fres, READ_RESTART_LINE,
+                    &workspace->orig_id[i], &p_atom->type, p_atom->name,
+                    &p_atom->x[0], &p_atom->x[1], &p_atom->x[2],
+                    &p_atom->v[0], &p_atom->v[1], &p_atom->v[2] ) != 9 )
+        {
+            fprintf( stderr, "[ERROR] reading restart file failed\n" \
+                    "  [INFO] reading atom info (%d entry)\n", i );
+            exit( INVALID_INPUT );
+        }
         workspace->map_serials[workspace->orig_id[i]] = i;
     }
 
diff --git a/sPuReMD/src/traj.c b/sPuReMD/src/traj.c
index 896c0400..5b957117 100644
--- a/sPuReMD/src/traj.c
+++ b/sPuReMD/src/traj.c
@@ -581,11 +581,21 @@ void Read_Traj_Compressed( output_controls *out_control, char *traj_name )
 
         if ( strnlen( size_buffer, 50 ) >= SIZE_INFO_LEN3 )
         {
-            sscanf( size_buffer, "%d %d %d", &skip_all, &skip_part, &n );
+            if ( sscanf( size_buffer, "%d %d %d", &skip_all, &skip_part, &n ) != 3 )
+            {
+                fprintf( stderr, "[ERROR] reading trajectory file failed\n" \
+                         "  [INFO] reading skip info\n" );
+                exit( INVALID_INPUT );
+            }
         }
         else
         {
-            sscanf( size_buffer, "%d %d", &skip_all, &skip_part );
+            if ( sscanf( size_buffer, "%d %d", &skip_all, &skip_part ) != 2 )
+            {
+                fprintf( stderr, "[ERROR] reading trajectory file failed\n" \
+                         "  [INFO] reading skip info\n" );
+                exit( INVALID_INPUT );
+            }
         }
 
         fprintf( stderr, "%d %d\n", skip_all, skip_part );
-- 
GitLab