diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index bd85975d..5b6aa650 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -60,18 +60,23 @@ jobs: - name: install dependencies run: | sudo apt-get update - sudo apt-get install libhdf5-dev emacs + sudo apt-get install libhdf5-dev emacs libtool-bin valgrind - name: configure with autotools run: | ./autogen.sh - ./configure --enable-silent-rules + ./configure --enable-silent-rules - name: compile TREXIO run: make -j2 - name: check TREXIO - run: make -j2 check # Non-parallel run + run: make -j2 check + + - name: check via valgrind + run: | + which libtool + cd tests && ./run_valgrind.sh - name: Archive test log file if: failure() @@ -113,15 +118,15 @@ jobs: - name: maintainer clean run: make maintainer-clean - - name: reconfigure with clang and AddressSanitizer + - name: reconfigure with debugging run: | ./autogen.sh - ./configure CC=clang-15 CFLAGS="-O2 -fsanitize=address -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address" --enable-silent-rules + ./configure --enable-silent-rules --enable-debug --enable-sanitizer - name: recompile TREXIO run: make -j2 - - name: recheck TREXIO for memory leaks + - name: recheck TREXIO run: make -j2 check - name: Archive test log file diff --git a/configure.ac b/configure.ac index 7d096f8b..56fa0159 100644 --- a/configure.ac +++ b/configure.ac @@ -53,9 +53,9 @@ AS_IF([test "$ok" = "yes"],[ # Specific options required with some compilers AS_CASE([$FC], - [*gfortran*], [FCFLAGS="$FCFLAGS -g -fPIC"], - [*flang*], [FCFLAGS="$FCFLAGS -g -fPIC"], - [*ifort*], [FCFLAGS="$FCFLAGS -g -fPIC"], + [*gfortran*], [FCFLAGS="$FCFLAGS -fPIC"], + [*flang*], [FCFLAGS="$FCFLAGS -fPIC"], + [*ifort*], [FCFLAGS="$FCFLAGS -fPIC"], []) ]) @@ -131,7 +131,7 @@ AC_ARG_WITH([hdf5], AS_HELP_STRING([--with-hdf5=PATH], [Path to HDF5 library and headers]), [ with_hdf5="$withval"], [with_hdf5="yes"]) -AS_IF([test "x$with_hdf5" == "xno"], [], +AS_IF([test "x$with_hdf5" == "xno"], [], [test "x$with_hdf5" != "xyes"], [ HDF5_LIBS="-lhdf5" HDF5_PATH="$with_hdf5" @@ -312,6 +312,21 @@ AC_CHECK_HEADERS([math.h]) AC_SEARCH_LIBS([pthread_create], [pthread], [], AC_MSG_ERROR([The pthread library is required])) AC_CHECK_HEADERS([pthread.h]) +# Debug flags + +AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug],[enable gcc and gfortran debug flags])], ok=$enableval, ok=no) +if test "$ok" = "yes"; then + CFLAGS="${CFLAGS} -Wall -Wextra -Wpedantic -Werror -Wshadow -Wformat -Wfloat-equal -Wconversion -Wcast-align -Wnull-dereference -Wstrict-aliasing -Winline -Wmissing-prototypes -Wunreachable-code -fstack-protector-strong -fdiagnostics-show-option -Wfloat-conversion -Wcast-qual -fno-inline -fno-omit-frame-pointer -Wno-sign-conversion -Wno-cast-qual -Wno-float-conversion" # -Wno-unused-variable" + FCFLAGS="${FCFLAGS} -g -fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant -Wuninitialized -fbacktrace -ffpe-trap=zero,overflow -finit-real=nan" +fi + + +AC_ARG_ENABLE(sanitizer, [AS_HELP_STRING([--enable-sanitizer],[enable sanitizer debug flags])], ok=$enableval, ok=no) +if test "$ok" = "yes"; then + CFLAGS="${CFLAGS} -fsanitize=address -fsanitize=undefined -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=bounds -fsanitize=bounds-strict" + FCFLAGS="${FCFLAGS} -fsanitize=address -fsanitize=undefined -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=bounds -fsanitize=bounds-strict" +fi + AC_CONFIG_FILES([Makefile pkgconfig/trexio.pc]) diff --git a/src/templates_front/templator_front.org b/src/templates_front/templator_front.org index 524c3d2d..ddbe43b4 100644 --- a/src/templates_front/templator_front.org +++ b/src/templates_front/templator_front.org @@ -471,12 +471,19 @@ __trexio_path__ = None | ~TREXIO_VERSION_PARSING_ISSUE~ | 36 | 'Failed to parse package_version' | | ~TREXIO_PHASE_CHANGE~ | 37 | 'The function succeeded with a change of sign' | | ~TREXIO_INVALID_MO_INDEX~ | 38 | 'Invalid MO index' | + | ~TREXIO_INVALID_ARG_9~ | 39 | 'Invalid argument 9' | + | ~TREXIO_INVALID_ARG_10~ | 40 | 'Invalid argument 10' | + | ~TREXIO_INVALID_ARG_11~ | 41 | 'Invalid argument 11' | + | ~TREXIO_INVALID_ARG_12~ | 42 | 'Invalid argument 12' | + | ~TREXIO_INVALID_ARG_13~ | 43 | 'Invalid argument 13' | + | ~TREXIO_INVALID_ARG_14~ | 44 | 'Invalid argument 14' | + | ~TREXIO_CORRUPTION_ATTEMPT~ | 45 | 'File offset is wrong, corruption risk' | # We need to force Emacs not to indent the Python code: # -*- org-src-preserve-indentation: t *IMPORTANT!* - The code below has to be executed within Emacs each time + The 2 code blocks below have to be executed within Emacs each time a new error code is added to the table above. Otherwise, the codes and the corresponding message are not propagated to the source code. @@ -512,7 +519,6 @@ return '\n'.join(result) #+end_src - #+RESULTS: :results: #+begin_src c :tangle prefix_front.h :exports none @@ -556,6 +562,13 @@ return '\n'.join(result) #define TREXIO_VERSION_PARSING_ISSUE ((trexio_exit_code) 36) #define TREXIO_PHASE_CHANGE ((trexio_exit_code) 37) #define TREXIO_INVALID_MO_INDEX ((trexio_exit_code) 38) + #define TREXIO_INVALID_ARG_9 ((trexio_exit_code) 39) + #define TREXIO_INVALID_ARG_10 ((trexio_exit_code) 40) + #define TREXIO_INVALID_ARG_11 ((trexio_exit_code) 41) + #define TREXIO_INVALID_ARG_12 ((trexio_exit_code) 42) + #define TREXIO_INVALID_ARG_13 ((trexio_exit_code) 43) + #define TREXIO_INVALID_ARG_14 ((trexio_exit_code) 44) + #define TREXIO_CORRUPTION_ATTEMPT ((trexio_exit_code) 45) #+end_src #+begin_src f90 :tangle prefix_fortran.f90 :exports none @@ -599,6 +612,13 @@ return '\n'.join(result) integer(trexio_exit_code), parameter :: TREXIO_VERSION_PARSING_ISSUE = 36 integer(trexio_exit_code), parameter :: TREXIO_PHASE_CHANGE = 37 integer(trexio_exit_code), parameter :: TREXIO_INVALID_MO_INDEX = 38 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_9 = 39 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_10 = 40 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_11 = 41 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_12 = 42 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_13 = 43 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_14 = 44 + integer(trexio_exit_code), parameter :: TREXIO_CORRUPTION_ATTEMPT = 45 #+end_src #+begin_src python :tangle prefix_python.py :exports none @@ -643,31 +663,16 @@ return '\n'.join(result) TREXIO_VERSION_PARSING_ISSUE = 36 TREXIO_PHASE_CHANGE = 37 TREXIO_INVALID_MO_INDEX = 38 + TREXIO_INVALID_ARG_9 = 39 + TREXIO_INVALID_ARG_10 = 40 + TREXIO_INVALID_ARG_11 = 41 + TREXIO_INVALID_ARG_12 = 42 + TREXIO_INVALID_ARG_13 = 43 + TREXIO_INVALID_ARG_14 = 44 + TREXIO_CORRUPTION_ATTEMPT = 45 #+end_src :end: -*** Decoding errors - - The ~trexio_string_of_error~ converts an exit code into a string. The - string is assumed to be large enough to contain the error message - (typically 128 characters). - - To decode the error messages, ~trexio_string_of_error~ converts an - error code into a string. - - #+NAME: MAX_STRING_LENGTH - : 128 - - #+begin_src c :tangle prefix_front.h :exports none :noweb yes -const char* trexio_string_of_error(const trexio_exit_code error); -void trexio_string_of_error_f(const trexio_exit_code error, char result[<>]); - #+end_src - - *IMPORTANT!* - The code below has to be executed within Emacs each time - a new error code is added to the table above. Otherwise, the codes - and the corresponding message are not propagated to the source code. - #+NAME:cases #+begin_src python :var table=table-exit-codes :exports none :noweb yes """ This script extracts the text associated with the error codes @@ -799,8 +804,49 @@ return '\n'.join(result) case TREXIO_VERSION_PARSING_ISSUE: return "Failed to parse package_version"; break; + case TREXIO_PHASE_CHANGE: + return "The function succeeded with a change of sign"; + break; + case TREXIO_INVALID_MO_INDEX: + return "Invalid MO index"; + break; + case TREXIO_INVALID_ARG_9: + return "Invalid argument 9"; + break; + case TREXIO_INVALID_ARG_10: + return "Invalid argument 10"; + break; + case TREXIO_INVALID_ARG_11: + return "Invalid argument 11"; + break; + case TREXIO_INVALID_ARG_12: + return "Invalid argument 12"; + break; + case TREXIO_INVALID_ARG_13: + return "Invalid argument 13"; + break; + case TREXIO_INVALID_ARG_14: + return "Invalid argument 14"; + break; + case TREXIO_CORRUPTION_ATTEMPT: + return "File offset is wrong, corruption risk"; + break; #+end_example +*** Decoding errors + + The ~trexio_string_of_error~ converts an exit code into a string. The + string is assumed to be large enough to contain the error message + (typically 128 characters). + + To decode the error messages, ~trexio_string_of_error~ converts an + error code into a string. + + #+begin_src c :tangle prefix_front.h :exports none :noweb yes +const char* trexio_string_of_error(const trexio_exit_code error); +void trexio_string_of_error_f(const trexio_exit_code error, const int32_t size_string, char* const result); + #+end_src + **** C source code #+begin_src c :tangle prefix_front.c :noweb yes @@ -814,9 +860,17 @@ trexio_string_of_error (const trexio_exit_code error) } void -trexio_string_of_error_f (const trexio_exit_code error, char result[<>]) +trexio_string_of_error_f (const trexio_exit_code error, const int32_t str_size, char* const result) { - strncpy(result, trexio_string_of_error(error), <>); + const char* pSrc = trexio_string_of_error(error); + int32_t sizeCp = (int32_t) strlen(pSrc); + if (sizeCp > str_size) { + sizeCp = str_size; + } + memcpy(result, pSrc, sizeCp); + for (int32_t i=sizeCp ; i>) - end subroutine trexio_string_of_error + integer(c_int32_t), intent(in), value :: str_size + character(kind=c_char), intent(out) :: string(str_size) + end subroutine trexio_string_of_error_f end interface #+end_src @@ -1266,8 +1321,11 @@ trexio_open(const char* file_name, const char mode, /* Data for the parent type */ - strncpy(result->file_name, file_name, TREXIO_MAX_FILENAME_LENGTH); - if (result->file_name[TREXIO_MAX_FILENAME_LENGTH-1] != '\0') { + // See https://stackoverflow.com/a/50198398/4151327 + size_t lenSrc = strnlen(file_name, TREXIO_MAX_FILENAME_LENGTH-1); + if (lenSrc < TREXIO_MAX_FILENAME_LENGTH) { + memcpy(result->file_name, file_name, lenSrc+1); + } else { if (rc_open != NULL) *rc_open = TREXIO_INVALID_ARG_1; free(result); return NULL; @@ -1285,11 +1343,9 @@ trexio_open(const char* file_name, const char mode, } // assert (irc == 0); - trexio_exit_code rc; - /* Back end initialization */ - rc = TREXIO_OPEN_ERROR; + trexio_exit_code rc = TREXIO_OPEN_ERROR; switch (back_end_local) { @@ -2090,8 +2146,6 @@ trexio_pre_close (trexio_t* file) if (file == NULL) return TREXIO_FILE_ERROR; - trexio_exit_code rc; - /* Check consistency between number of determinants and coefficients stored in the file */ if (file->version_major >= 2 && file->version_minor >= 2) { @@ -2101,6 +2155,8 @@ trexio_pre_close (trexio_t* file) int64_t ndet, ncoeff; if (has_det && has_coeff) { + trexio_exit_code rc = TREXIO_FAILURE; + rc = trexio_read_determinant_num_64(file, &ndet); if (rc != TREXIO_SUCCESS) return rc; @@ -2120,7 +2176,11 @@ trexio_pre_close (trexio_t* file) bool has_updn = (trexio_has_electron_num(file) == TREXIO_SUCCESS); if (file->mode != 'r') { + if (has_updn && has_up && has_dn) { + + trexio_exit_code rc = TREXIO_FAILURE; + rc = trexio_read_electron_up_num(file, &nup); if (rc != TREXIO_SUCCESS) return rc; @@ -2139,7 +2199,11 @@ trexio_pre_close (trexio_t* file) return TREXIO_INVALID_ELECTRON_NUM; } } + } else if (has_up && has_dn) { + + trexio_exit_code rc = TREXIO_FAILURE; + rc = trexio_read_electron_up_num(file, &nup); if (rc != TREXIO_SUCCESS) return rc; @@ -2149,7 +2213,11 @@ trexio_pre_close (trexio_t* file) nelec = nup + ndn; rc = trexio_write_electron_num(file, nelec); if (rc != TREXIO_SUCCESS) return rc; + } else if (has_up) { + + trexio_exit_code rc = TREXIO_FAILURE; + rc = trexio_read_electron_up_num(file, &nup); if (rc != TREXIO_SUCCESS) return rc; @@ -2160,7 +2228,11 @@ trexio_pre_close (trexio_t* file) nelec = nup; rc = trexio_write_electron_num(file, nelec); if (rc != TREXIO_SUCCESS) return rc; + } else if (has_dn) { + + trexio_exit_code rc = TREXIO_FAILURE; + rc = trexio_read_electron_dn_num(file, &ndn); if (rc != TREXIO_SUCCESS) return rc; @@ -2171,6 +2243,7 @@ trexio_pre_close (trexio_t* file) nelec = ndn; rc = trexio_write_electron_num(file, nelec); if (rc != TREXIO_SUCCESS) return rc; + } } @@ -2792,9 +2865,10 @@ trexio_read_$group_dset$_64 (trexio_t* const file, $group_dset_dtype_double$* co if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; if (trexio_has_$group_dset$(file) != TREXIO_SUCCESS) return TREXIO_DSET_MISSING; - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; + trexio_exit_code rc = TREXIO_FAILURE; + /* Error handling for this call is added by the generator */ rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); @@ -2855,10 +2929,9 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS; - - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; + trexio_exit_code rc = TREXIO_FAILURE; /* Error handling for this call is added by the generator */ rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); @@ -2952,9 +3025,10 @@ trexio_read_$group_dset$_32 (trexio_t* const file, $group_dset_dtype_single$* co if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; if (trexio_has_$group_dset$(file) != TREXIO_SUCCESS) return TREXIO_DSET_MISSING; - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; + trexio_exit_code rc = TREXIO_FAILURE; + /* Error handling for this call is added by the generator */ rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); @@ -3026,9 +3100,10 @@ trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_sing if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS; - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; + trexio_exit_code rc = TREXIO_FAILURE; + /* Error handling for this call is added by the generator */ rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); @@ -3092,9 +3167,11 @@ trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_sing #+NAME:dimCheck #+begin_src c - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; + trexio_exit_code rc = TREXIO_FAILURE; + (void) rc; // Avoids unused parameter error for scalar variables + /* Error handling for this call is added by the generator */ rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); @@ -3578,6 +3655,12 @@ trexio_exit_code trexio_read_safe_$group_dset$(trexio_t* const file, const int64_t size_value_read ) { + /* To be set by generator : number of indices */ + const uint32_t rank = $group_dset_rank$; + + if (size_index_read < rank * (*buffer_size_read)) return TREXIO_INVALID_ARG_5; + if (size_value_read < (*buffer_size_read)) return TREXIO_INVALID_ARG_7; + return trexio_read_$group_dset$(file, offset_file, buffer_size_read, index_sparse_read, value_sparse_read); } @@ -3599,10 +3682,9 @@ trexio_read_$group_dset$(trexio_t* const file, const uint32_t rank = $group_dset_rank$; // To be set by generator : number of indices int64_t size_max; // Max number of integrals (already in the file) - trexio_exit_code rc; /* Read the max number of integrals stored in the file */ - rc = trexio_read_$group_dset$_size(file, &size_max); + trexio_exit_code rc = trexio_read_$group_dset$_size(file, &size_max); if (rc != TREXIO_SUCCESS) return rc; /* To be set by generator : number of unique dimensions @@ -3710,6 +3792,12 @@ trexio_exit_code trexio_write_safe_$group_dset$(trexio_t* const file, const int64_t size_value_write ) { + /* To be set by generator : number of indices */ + const uint32_t rank = $group_dset_rank$; + + if (size_index_write < rank * buffer_size) return TREXIO_INVALID_ARG_5; + if (size_value_write < buffer_size) return TREXIO_INVALID_ARG_7; + return trexio_write_$group_dset$(file, offset_file, buffer_size, index_sparse_write, value_sparse_write); } @@ -3731,13 +3819,15 @@ trexio_write_$group_dset$(trexio_t* const file, const uint32_t rank = $group_dset_rank$; int64_t size_max = 0L; // Max number of integrals (already in the file) - trexio_exit_code rc; /* Read the max number of integrals stored in the file */ - rc = trexio_read_$group_dset$_size(file, &size_max); + trexio_exit_code rc = trexio_read_$group_dset$_size(file, &size_max); if (rc != TREXIO_SUCCESS && rc != TREXIO_DSET_MISSING) return rc; if (rc == TREXIO_DSET_MISSING) size_max = 0L; + /* Dummy check to avoid overwriting existing data */ + if (offset_file < size_max) return TREXIO_CORRUPTION_ATTEMPT; + /* To be set by generator : number of unique dimensions (e.g. 1 for ERI in AO basis because only ao_num is present in the list of dimensions) */ #define unique_rank $group_dset_unique_rank$ @@ -4182,11 +4272,10 @@ trexio_read_$group_dset$_low (trexio_t* const file, char* dset_out, const int32_ if (max_str_len <= 0) return TREXIO_INVALID_ARG_3; if (trexio_has_$group_dset$(file) != TREXIO_SUCCESS) return TREXIO_DSET_MISSING; - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; /* Error handling for this call is added by the generator */ - rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); + trexio_exit_code rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM; @@ -4225,11 +4314,10 @@ trexio_read_$group_dset$ (trexio_t* const file, char** dset_out, const int32_t m assert(file->back_end < TREXIO_INVALID_BACK_END); - trexio_exit_code rc; int64_t dset_dim = 0; /* Error handling for this call is added by the generator */ - rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim)); + trexio_exit_code rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim)); if (dset_dim == 0L) return TREXIO_INVALID_NUM; @@ -4272,11 +4360,10 @@ trexio_write_$group_dset$_low (trexio_t* const file, char* dset_in, const int32_ if (max_str_len <= 0) return TREXIO_INVALID_ARG_3; if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS; - trexio_exit_code rc; int64_t $group_dset_dim$ = 0; /* Error handling for this call is added by the generator */ - rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); + trexio_exit_code rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$)); if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM; @@ -4358,11 +4445,10 @@ trexio_write_$group_dset$ (trexio_t* const file, const char** dset_in, const int assert(file->back_end < TREXIO_INVALID_BACK_END); - trexio_exit_code rc; int64_t dset_dim = 0; /* Error handling for this call is added by the generator */ - rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim)); + trexio_exit_code rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim)); if (dset_dim == 0L) return TREXIO_INVALID_NUM; @@ -4631,7 +4717,7 @@ trexio_read_$group_dset$ (trexio_t* const file, const int64_t offset_file, int64 if (dset == NULL) return TREXIO_INVALID_ARG_2; if (trexio_has_$group_dset$(file) != TREXIO_SUCCESS) return TREXIO_DSET_MISSING; - trexio_exit_code rc; + trexio_exit_code rc = TREXIO_FAILURE; uint32_t rank = 1; uint64_t det_size = (uint64_t) (*buffer_size_read); @@ -4660,8 +4746,8 @@ trexio_read_$group_dset$ (trexio_t* const file, const int64_t offset_file, int64 break; ,*/ default: - rc = TREXIO_FAILURE; /* Impossible case */ - break; + rc = TREXIO_FAILURE; + break; /* Impossible case */ } if (rc != TREXIO_SUCCESS && rc != TREXIO_END) return rc; @@ -4709,6 +4795,7 @@ trexio_read_$group_dset$_size(trexio_t* const file, int64_t* const size_max) trexio_exit_code trexio_read_safe_$group_dset$ (trexio_t* const file, const int64_t offset_file, int64_t* const buffer_size_read, double* const dset_out, const int64_t dim_out) { + if (dim_out < (*buffer_size_read)) return TREXIO_INVALID_ARG_5; return trexio_read_$group_dset$(file, offset_file, buffer_size_read, dset_out); } #+end_src @@ -4755,6 +4842,9 @@ trexio_write_$group_dset$ (trexio_t* const file, const int64_t offset_file, cons trexio_exit_code trexio_write_safe_$group_dset$ (trexio_t* const file, const int64_t offset_file, const int64_t buffer_size, const double* dset_in, const int64_t dim_in) { + /* Check that dim_in is large enough */ + if (dim_in < buffer_size) return TREXIO_INVALID_ARG_5; + return trexio_write_$group_dset$(file, offset_file, buffer_size, dset_in); } #+end_src @@ -5384,7 +5474,7 @@ trexio_get_int64_num(trexio_t* const file, int32_t* const num) /* Compute how many integer numbers is needed to represent a determinant */ int32_t int_num = 0; - int_num = (mo_num - 1L)/64 + 1; + int_num = (int32_t) (mo_num - 1L)/64 + 1; *num = int_num; @@ -5452,6 +5542,14 @@ trexio_read_determinant_list (trexio_t* const file, const int64_t offset_file, i trexio_exit_code trexio_read_safe_determinant_list (trexio_t* const file, const int64_t offset_file, int64_t* const buffer_size_read, int64_t* const dset_out, const int64_t dim_out) { + /* Get the number of int bit fields per determinant */ + int32_t int_num = 0; + trexio_exit_code rc = trexio_get_int64_num(file, &int_num); + if (rc != TREXIO_SUCCESS) return rc; + + /* Check that dset_out is large enough */ + if (dim_out < (*buffer_size_read) * int_num * 2) return TREXIO_INVALID_ARG_5; + return trexio_read_determinant_list(file, offset_file, buffer_size_read, dset_out); } #+end_src @@ -5472,6 +5570,17 @@ trexio_write_determinant_list (trexio_t* const file, const int64_t offset_file, if (buffer_size <= 0) return TREXIO_INVALID_ARG_3; if (dset == NULL) return TREXIO_INVALID_ARG_4; + // Update the determinant_num value with the number of determinants written + int64_t det_num_current = 0L; + // Read the determinant_num if it exists already + if (trexio_has_determinant_num(file) == TREXIO_SUCCESS) { + trexio_exit_code rc = trexio_read_determinant_num_64(file, &det_num_current); + if (rc != TREXIO_SUCCESS) return rc; + } + + /* Dummy check to avoid overwriting existing data */ + if (offset_file < det_num_current) return TREXIO_CORRUPTION_ATTEMPT; + /* Get the number of int bit fields per determinant */ int32_t int_num = 0; trexio_exit_code rc = trexio_get_int64_num(file, &int_num); @@ -5587,6 +5696,14 @@ trexio_write_determinant_list (trexio_t* const file, const int64_t offset_file, trexio_exit_code trexio_write_safe_determinant_list (trexio_t* const file, const int64_t offset_file, const int64_t buffer_size, const int64_t* dset_in, const int64_t dim_in) { + /* Get the number of int bit fields per determinant */ + int32_t int_num = 0; + trexio_exit_code rc = trexio_get_int64_num(file, &int_num); + if (rc != TREXIO_SUCCESS) return rc; + + /* Check that dim_in is large enough */ + if (dim_in < buffer_size * int_num * 2) return TREXIO_INVALID_ARG_5; + return trexio_write_determinant_list(file, offset_file, buffer_size, dset_in); } #+end_src @@ -6048,10 +6165,8 @@ trexio_exit_code trexio_to_orbital_list_up_dn(const int32_t N_int, if (occ_num_up == NULL) return TREXIO_INVALID_ARG_5; if (occ_num_dn == NULL) return TREXIO_INVALID_ARG_6; - trexio_exit_code rc; - /* First process up-spin electrons */ - rc = trexio_to_orbital_list(N_int, &d1[0], list_up, occ_num_up); + trexio_exit_code rc = trexio_to_orbital_list(N_int, &d1[0], list_up, occ_num_up); if (rc != TREXIO_SUCCESS) return rc; /* Now process down-spin electrons */ @@ -6071,6 +6186,14 @@ trexio_safe_to_orbital_list (const int32_t N_int, const int64_t dim_out, int32_t* const num) { + if (dim_in < N_int) return TREXIO_INVALID_ARG_3; + + /* Count number of up electrons in first bitfield */ + int count = 0; + for (int i=0 ; i= grid_size[shell_index]) @@ -6158,7 +6296,7 @@ trexio_evaluate_nao_radial (const int32_t shell_index, const double r, const int val_spline += t * t * interpolator[i0 + 4*i_log + 2]; val_spline += t * t * t * interpolator[i0 + 4*i_log + 3]; - *amplitude = val_spline * normalization[shell_index] / r; + ,*amplitude = val_spline * normalization[shell_index] / r; return TREXIO_SUCCESS; } @@ -6176,8 +6314,6 @@ trexio_evaluate_nao_radial_all (const int32_t shell_num, const int32_t* const nu if (interpolator == 0) return TREXIO_INVALID_ARG_7; if (normalization == 0) return TREXIO_INVALID_ARG_8; - trexio_exit_code rc; - for (int shell_index = 0; shell_index < shell_num; shell_index++) { const int32_t nuc_index = nucleus_index[shell_index]; const double dx = nucleus_coords[3*nuc_index + 0] - rx; @@ -6186,7 +6322,7 @@ trexio_evaluate_nao_radial_all (const int32_t shell_num, const int32_t* const nu const double r = sqrt(dx*dx + dy*dy + dz*dz); // All possibly reported errors have been caught above - rc = trexio_evaluate_nao_radial(shell_index, r, grid_start, + trexio_exit_code rc = trexio_evaluate_nao_radial(shell_index, r, grid_start, grid_size, grid_r, interpolator, normalization, &litude[shell_index]); if (rc != TREXIO_SUCCESS) @@ -6199,39 +6335,47 @@ trexio_evaluate_nao_radial_all (const int32_t shell_num, const int32_t* const nu trexio_exit_code trexio_evaluate_nao_radial_py (const int shell_index, const double r, int64_t* grid_start, int n_grid_st, int64_t* grid_size, int n_grid_si, double* grid_r, int n_grid_r, - double* interpolator, int n_interp, double* normalization, int n_norm, double* const amplitude) + double* interpolator, int n_interp, double* normalization, int n_norm, + double* const amplitude) { // Code needs to be copied because of the use of int64_t mandated by Python // If a 64-bit version is implemented, this can be avoided if (shell_index < 0) return TREXIO_INVALID_ARG_1; if (r < 0) return TREXIO_INVALID_ARG_2; if (grid_start == 0) return TREXIO_INVALID_ARG_3; - if (grid_size == 0) return TREXIO_INVALID_ARG_4; - if (grid_r == NULL) return TREXIO_INVALID_ARG_5; - if (interpolator == 0) return TREXIO_INVALID_ARG_6; - if (normalization == 0) return TREXIO_INVALID_ARG_7; + if (n_grid_st < shell_index) return TREXIO_INVALID_ARG_4; + if (grid_size == 0) return TREXIO_INVALID_ARG_5; + if (n_grid_si < shell_index) return TREXIO_INVALID_ARG_6; + if (grid_r == NULL) return TREXIO_INVALID_ARG_7; + if (n_grid_r < grid_start[shell_index]) return TREXIO_INVALID_ARG_8; + if (interpolator == NULL) return TREXIO_INVALID_ARG_9; + if (normalization == 0) return TREXIO_INVALID_ARG_11; + if (n_norm < shell_index) return TREXIO_INVALID_ARG_12; - const int32_t i0 = 4*grid_start[shell_index]; + const int64_t i0 = 4*grid_start[shell_index]; + if (n_interp < i0) return TREXIO_INVALID_ARG_10; // Convert radius to logarithmic units double r_log = 0.0; trexio_convert_nao_radius_64 (r, grid_r + grid_start[shell_index], &r_log); - int32_t i_log = (int32_t) r_log; + int64_t i_log = (int64_t) r_log; if (i_log < 0) { - *amplitude = interpolator[i0] * normalization[shell_index] / r; + ,*amplitude = interpolator[i0] * normalization[shell_index] / r; return TREXIO_SUCCESS; } else if (i_log >= grid_size[shell_index]) { - *amplitude = 0.0; + ,*amplitude = 0.0; return TREXIO_SUCCESS; // NAOs vanish at the boundary by definition } double t = r_log - (double) i_log; + if (n_interp < i0+4*i_log+3) return TREXIO_INVALID_ARG_10; + double val_spline = interpolator[i0 + 4*i_log + 0]; val_spline += t * interpolator[i0 + 4*i_log + 1]; val_spline += t * t * interpolator[i0 + 4*i_log + 2]; val_spline += t * t * t * interpolator[i0 + 4*i_log + 3]; - *amplitude = val_spline * normalization[shell_index] / r; + ,*amplitude = val_spline * normalization[shell_index] / r; return TREXIO_SUCCESS; } @@ -6240,29 +6384,38 @@ trexio_exit_code trexio_evaluate_nao_radial_all_py (const int32_t shell_num, int64_t* grid_start, int n_grid_st, int64_t* grid_size, int n_grid_si, double* grid_r, int n_grid_r, double* interpolator, int n_interp, double* normalization, int n_norm, - const double rx, const double ry, const double rz, double* const amplitudes, int amplitude_cnt) + const double rx, const double ry, const double rz, + double* const amplitudes, int amplitude_cnt) { if (shell_num < 0) return TREXIO_INVALID_ARG_1; - if (nucleus_index == 0) return TREXIO_INVALID_ARG_2; - if (nucleus_coords == 0) return TREXIO_INVALID_ARG_3; - if (grid_start == 0) return TREXIO_INVALID_ARG_4; - if (grid_size == 0) return TREXIO_INVALID_ARG_5; - if (grid_r == NULL) return TREXIO_INVALID_ARG_6; - if (interpolator == 0) return TREXIO_INVALID_ARG_7; - if (normalization == 0) return TREXIO_INVALID_ARG_8; + if (nucleus_index == NULL) return TREXIO_INVALID_ARG_2; + if (nucleus_coords == NULL) return TREXIO_INVALID_ARG_4; + if (grid_start == NULL) return TREXIO_INVALID_ARG_6; + if (grid_size == NULL) return TREXIO_INVALID_ARG_8; + if (grid_r == NULL) return TREXIO_INVALID_ARG_10; + if (interpolator == NULL) return TREXIO_INVALID_ARG_12; + if (normalization == NULL) return TREXIO_INVALID_ARG_14; + + assert (amplitudes != NULL); // 19 arguments!!! Don't want to make TREXIO_INVALID_ARG_19 + assert (amplitude_cnt > shell_num); - trexio_exit_code rc; + if (n_nuc_id < shell_num) return TREXIO_INVALID_ARG_3; + if (n_nuc_co < 3*nucleus_index[shell_num-1]+2) return TREXIO_INVALID_ARG_5; for (int shell_index = 0; shell_index < shell_num; shell_index++) { - const int32_t nuc_index = nucleus_index[shell_index]; + const int64_t nuc_index = nucleus_index[shell_index]; + const double dx = nucleus_coords[3*nuc_index + 0] - rx; const double dy = nucleus_coords[3*nuc_index + 1] - ry; const double dz = nucleus_coords[3*nuc_index + 2] - rz; const double r = sqrt(dx*dx + dy*dy + dz*dz); // All possibly reported errors have been caught above - rc = trexio_evaluate_nao_radial_py(shell_index, r, grid_start, n_grid_st, - grid_size, n_grid_si, grid_r, n_grid_r, interpolator, n_interp, normalization, n_norm, &litudes[shell_index]); + trexio_exit_code rc = + trexio_evaluate_nao_radial_py(shell_index, r, grid_start, n_grid_st, grid_size, + n_grid_si, grid_r, n_grid_r, interpolator, n_interp, + normalization, n_norm, &litudes[shell_index]); + if (rc != TREXIO_SUCCESS) return rc; } @@ -6664,6 +6817,18 @@ contains end function trexio_info #+end_src + This function adds the string length as an extra argument to help the C code + check that the passed string is large enough. + + #+begin_src f90 :tangle helper_fortran.f90 :noweb yes +subroutine trexio_string_of_error (error, string) + implicit none + integer(trexio_exit_code), intent(in) :: error + character*(*), intent(out) :: string + call trexio_string_of_error_f(error, len(string), string) +end subroutine trexio_string_of_error + #+end_src + The function below adapts the original C-based ~trexio_open~ for Fortran. This is needed due to the fact that strings in C are terminated by ~NULL~ character ~\0~ unlike strings in Fortran. diff --git a/src/templates_hdf5/templator_hdf5.org b/src/templates_hdf5/templator_hdf5.org index bdfa9bcf..bc412536 100644 --- a/src/templates_hdf5/templator_hdf5.org +++ b/src/templates_hdf5/templator_hdf5.org @@ -277,6 +277,7 @@ trexio_hdf5_write_$group_num$ (trexio_t* const file, const $group_num_dtype_doub { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (num < 0) return TREXIO_INVALID_ARG_2; trexio_hdf5_t* const f = (trexio_hdf5_t*) file; @@ -355,6 +356,8 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $ if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; @@ -412,6 +415,8 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; trexio_hdf5_t* f = (trexio_hdf5_t*) file; @@ -502,6 +507,11 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (size < 0) return TREXIO_INVALID_ARG_3; + if (size_max < 0) return TREXIO_INVALID_ARG_4; + if (index_sparse == NULL) return TREXIO_INVALID_ARG_5; + if (value_sparse == NULL) return TREXIO_INVALID_ARG_6; trexio_hdf5_t* f = (trexio_hdf5_t*) file; @@ -593,7 +603,12 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file, { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (size < 0) return TREXIO_INVALID_ARG_3; + if (size_max < 0) return TREXIO_INVALID_ARG_4; if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5; + if (index_read == NULL) return TREXIO_INVALID_ARG_6; + if (value_read == NULL) return TREXIO_INVALID_ARG_7; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; @@ -703,6 +718,9 @@ trexio_exit_code trexio_hdf5_read_$group_dset$(trexio_t* const file, double* const dset) { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank != 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5; if (dset == NULL) return TREXIO_INVALID_ARG_6; @@ -728,6 +746,9 @@ trexio_exit_code trexio_hdf5_write_$group_dset$(trexio_t* const file, { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank != 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (dset == NULL) return TREXIO_INVALID_ARG_5; const char* dset_name = "$group_dset$"; @@ -832,6 +853,9 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file, char* const $group_dset$, c if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; + if (max_str_len < 1) return TREXIO_INVALID_ARG_5; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; @@ -938,6 +962,8 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$, if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; trexio_hdf5_t* f = (trexio_hdf5_t*) file; @@ -1031,6 +1057,7 @@ trexio_hdf5_read_$group_str$ (trexio_t* const file, char* const str, const uint3 if (file == NULL) return TREXIO_INVALID_ARG_1; if (str == NULL) return TREXIO_INVALID_ARG_2; + if (max_str_len < 1) return TREXIO_INVALID_ARG_3; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; /* Quit if the string attribute is missing in the file */ @@ -1202,6 +1229,9 @@ trexio_exit_code trexio_hdf5_read_determinant_list(trexio_t* const file, int64_t* const list) { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank < 2) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5; if (list == NULL) return TREXIO_INVALID_ARG_6; @@ -1227,6 +1257,9 @@ trexio_exit_code trexio_hdf5_write_determinant_list(trexio_t* const file, { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank < 2) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (list == NULL) return TREXIO_INVALID_ARG_5; trexio_hdf5_t* f = (trexio_hdf5_t*) file; @@ -1292,6 +1325,9 @@ trexio_hdf5_create_write_dset_sparse (const hid_t group_id, const hsize_t* chunk_dims, const void* data_sparse) { + assert (chunk_dims != NULL); + assert (data_sparse != NULL); + assert (dset_name != NULL); const int h5_rank = 1; const hsize_t maxdims[1] = {H5S_UNLIMITED}; diff --git a/src/templates_text/templator_text.org b/src/templates_text/templator_text.org index d20f626c..27937458 100644 --- a/src/templates_text/templator_text.org +++ b/src/templates_text/templator_text.org @@ -222,6 +222,7 @@ trexio_text_init (trexio_t* const file) char file_name[TREXIO_MAX_FILENAME_LENGTH]; strncpy (file_name, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_name[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; strncat (file_name, lock_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(lock_file_name)); if (file_name[TREXIO_MAX_FILENAME_LENGTH-1] != '\0') { @@ -241,6 +242,7 @@ trexio_text_init (trexio_t* const file) char dirname[TREXIO_MAX_FILENAME_LENGTH] = "/tmp/trexio.XXXXXX"; if (mkdtemp(dirname) == NULL) return TREXIO_ERRNO; strncpy (file_name, dirname, TREXIO_MAX_FILENAME_LENGTH); + file_name[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; strncat (file_name, lock_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(lock_file_name)); f->lock_file = open(file_name,O_WRONLY|O_CREAT|O_TRUNC, 0644); remove(file_name); @@ -332,8 +334,7 @@ trexio_text_flush (trexio_t* const file) trexio_exit_code rc; trexio_text_t* f = (trexio_text_t*) file; - /* Error handling for this call is added by the generator */ - rc = trexio_text_flush_$group$(f); + rc = trexio_text_flush_$group$(f); if (rc != TREXIO_SUCCESS) return rc; return TREXIO_SUCCESS; @@ -368,6 +369,7 @@ trexio_text_read_$group$ (trexio_text_t* const file) const char* $group$_file_name = "/$group$.txt"; strncpy ($group$->file_name, file->parent.file_name, TREXIO_MAX_FILENAME_LENGTH); + $group$->file_name[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; strncat ($group$->file_name, $group$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group$_file_name)); @@ -394,7 +396,9 @@ trexio_text_read_$group$ (trexio_text_t* const file) } int rc = 0; + (void) rc; // Avoid unused variable; trexio_exit_code rc_free = TREXIO_FAILURE; + (void) rc_free; // Avoid unused variable; /* workaround for the case of missing blocks in the file */ // START REPEAT GROUP_DSET_ALL @@ -466,16 +470,16 @@ trexio_text_read_$group$ (trexio_text_t* const file) } /* WARNING: this tmp array allows to avoid allocation of space for each element of array of string - * BUT it's size has to be number_of_str*max_len_str where max_len_str is somewhat arbitrary, e.g. 32. - */ + ,* BUT it's size has to be number_of_str*max_len_str where max_len_str is somewhat arbitrary, e.g. 32. + ,*/ char* tmp_$group_dset$; tmp_$group_dset$ = CALLOC(size_$group_dset$*32, char); for (uint64_t i=0 ; i$group_dset$[i] = tmp_$group_dset$; /* conventional fcanf with "%s" only return the string before the first space character - * to read string with spaces use "%[^\n]" possible with space before or after, i.e. " %[^\n]" - */ + ,* to read string with spaces use "%[^\n]" possible with space before or after, i.e. " %[^\n]" + ,*/ rc = fscanf(f, " %1023[^\n]", buffer); if (rc != 1) { trexio_text_free_read_$group$(buffer, f, file, $group$); @@ -484,6 +488,7 @@ trexio_text_read_$group$ (trexio_text_t* const file) size_t tmp_$group_dset$_len = strlen(buffer); strncpy(tmp_$group_dset$, buffer, 32); + tmp_$group_dset$[31] = '\0'; tmp_$group_dset$ += tmp_$group_dset$_len + 1; } } @@ -548,6 +553,7 @@ trexio_text_read_$group$ (trexio_text_t* const file) } /* Safer string conversion to avoid buffer overflow in fscanf */ strncpy($group$->$group_str$, buffer, $group$->len_$group_str$); + $group$->$group_str$[$group$->len_$group_str$-1] = '\0'; } // END REPEAT GROUP_ATTR_STR @@ -592,6 +598,7 @@ trexio_text_has_$group$ (trexio_t* const file) const char* $group$_file_name = "/$group$.txt"; strncpy ($group$_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + $group$_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; strncat ($group$_full_path, $group$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group$_file_name)); @@ -721,6 +728,10 @@ trexio_text_free_$group$ (trexio_text_t* const file) This function is called upon the non-successful exit from the ~trexio_text_read_group~ function. + #+begin_src c :tangle free_group_text.h :exports none +trexio_exit_code trexio_text_free_read_$group$ (char* buffer, FILE* txt_file, trexio_text_t* trexio_file, $group$_t* $group$); + #+end_src + #+begin_src c :tangle free_group_text.c trexio_exit_code trexio_text_free_read_$group$ (char* buffer, FILE* txt_file, trexio_text_t* trexio_file, $group$_t* $group$) @@ -820,6 +831,8 @@ trexio_text_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $ if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; $group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file); if ($group$ == NULL) return TREXIO_FAILURE; @@ -849,6 +862,8 @@ trexio_text_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (file->mode == 'r') return TREXIO_READONLY; @@ -966,9 +981,10 @@ trexio_text_write_$group_dset$ (trexio_t* const file, const char** dset, const u if (tmp_str == NULL) return TREXIO_ALLOCATION_FAILED; for (uint64_t i=0 ; i$group_dset$[i] = tmp_str; strncpy(tmp_str, dset[i], tmp_len); + tmp_str[tmp_len-1] = '\0'; tmp_str += tmp_len + 1; } @@ -1017,6 +1033,7 @@ trexio_text_read_$group_str$ (trexio_t* const file, char* const str, const uint3 if ($group$ == NULL) return TREXIO_FAILURE; strncpy(str, $group$->$group_str$, max_str_len); + str[max_str_len-1] = '\0'; return TREXIO_SUCCESS; @@ -1046,6 +1063,7 @@ trexio_text_write_$group_str$ (trexio_t* const file, const char *str) $group$->len_$group_str$ = tmp_len + 1; strncpy($group$->$group_str$, str, tmp_len + 1); + $group$->$group_str$[tmp_len] = '\0'; $group$->to_flush = 1; @@ -1109,6 +1127,7 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, $group_dset$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group_dset$_file_name)); @@ -1121,6 +1140,8 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, the line_length is 69 because 10 per index + 4 spaces + 24 for floating point value + 1 for the new line char. CURRENTLY NO OFFSET IS USED WHEN WRITING ! ,*/ + (void) offset_file; // Avoid unused variable error + int64_t line_length = 0L; char format_str[256]; @@ -1128,12 +1149,15 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, if (size_max < UINT8_MAX) { line_length = $sparse_line_length_8$; // 41 for 4 indices strncpy(format_str, $sparse_format_printf_8$, 256); + format_str[255] = '\0'; } else if (size_max < UINT16_MAX) { line_length = $sparse_line_length_16$; // 49 for 4 indices strncpy(format_str, $sparse_format_printf_16$, 256); + format_str[255] = '\0'; } else { line_length = $sparse_line_length_32$; //69 for 4 indices strncpy(format_str, $sparse_format_printf_32$, 256); + format_str[255] = '\0'; } strncat(format_str, "\n", 2); @@ -1183,6 +1207,7 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH); /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, $group$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group$_file_name)); @@ -1222,6 +1247,7 @@ trexio_exit_code trexio_text_read_$group_dset$(trexio_t* const file, /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, $group_dset$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group_dset$_file_name)); @@ -1297,6 +1323,7 @@ trexio_exit_code trexio_text_read_$group_dset$_size(trexio_t* const file, int64_ /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, $group_dset$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group_dset$_file_name)); @@ -1347,6 +1374,7 @@ trexio_exit_code trexio_text_has_$group_dset$(trexio_t* const file) /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, $group_dset$_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen($group_dset$_file_name)); @@ -1383,6 +1411,9 @@ trexio_exit_code trexio_text_read_$group_dset$(trexio_t* const file, double* const dset) { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5; if (dset == NULL) return TREXIO_INVALID_ARG_6; @@ -1392,6 +1423,7 @@ trexio_exit_code trexio_text_read_$group_dset$(trexio_t* const file, char file_full_path[TREXIO_MAX_FILENAME_LENGTH]; /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, file_name, TREXIO_MAX_FILENAME_LENGTH - sizeof(file_name)); @@ -1454,6 +1486,7 @@ trexio_text_read_$group_dset$_size(trexio_t* const file, int64_t* const size_max char file_full_path[TREXIO_MAX_FILENAME_LENGTH]; /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, file_name, TREXIO_MAX_FILENAME_LENGTH - sizeof(file_name)); @@ -1495,6 +1528,9 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, const double* dset) { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank < 1) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (dset == NULL) return TREXIO_INVALID_ARG_5; const char file_name[256] = "/$group_dset$.txt"; @@ -1504,6 +1540,7 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, char file_full_path[TREXIO_MAX_FILENAME_LENGTH]; /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, file_name, TREXIO_MAX_FILENAME_LENGTH - sizeof(file_name)); @@ -1551,6 +1588,7 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH); /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, group_file_name, TREXIO_MAX_FILENAME_LENGTH - sizeof(group_file_name)); @@ -1579,6 +1617,7 @@ trexio_exit_code trexio_text_has_$group_dset$(trexio_t* const file) char file_full_path[TREXIO_MAX_FILENAME_LENGTH]; /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, file_name, TREXIO_MAX_FILENAME_LENGTH - sizeof(file_name)); @@ -1642,6 +1681,9 @@ trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, int64_t* const list) { if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank != 2) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5; if (list == NULL) return TREXIO_INVALID_ARG_6; @@ -1651,6 +1693,7 @@ trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, determinant_list_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name)); @@ -1660,12 +1703,13 @@ trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, if (f == NULL) return TREXIO_FILE_ERROR; /* Specify the line length in order to offset properly. - Each 64-bit integer takes at most 20 slots and requires one space, + Each 64-bit integer takes 20 slots and requires one space, + we have int_num integers per up-spin determinant, then this number is doubled because we have the same number for down-spin electrons, and then one newline char. ,*/ - uint64_t line_length = dims[1]*21UL + 1UL; // 20 digits per int64_t bitfield + 1 space = 11 spots + 1 newline char + uint64_t line_length = dims[1]*21UL + 1UL; // 20 digits per int64_t bitfield + 1 space = 21 spots + 1 newline char /* Offset in the file according to the provided value of offset_file and optimal line_length */ fseek(f, (long) offset_file * line_length, SEEK_SET); @@ -1673,8 +1717,8 @@ trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, /* Read the data from the file and check the return code of fprintf to verify that > 0 bytes have been read or reached EOF */ int rc; /* Declare fixed buffer which will be used to read the determinant string */ - char buffer[1024]; - uint32_t buf_size = sizeof(buffer); + char buffer[line_length+1]; + size_t buf_size = sizeof(buffer); /* Parameters to post-process the buffer and to get bit fields integers */ uint64_t accum = 0UL; uint32_t shift_int64 = 21U; @@ -1685,7 +1729,7 @@ trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, accum = 0UL; memset(buffer, 0, buf_size); - if (fgets(buffer, buf_size-1, f) == NULL){ + if (fgets(buffer, ( (int) line_length)+1, f) == NULL){ fclose(f); ,*eof_read_size = count; @@ -1724,7 +1768,10 @@ trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file, const uint64_t* dims, const int64_t* list) { - if (file == NULL) return TREXIO_INVALID_ARG_1; + if (file == NULL) return TREXIO_INVALID_ARG_1; + if (offset_file < 0) return TREXIO_INVALID_ARG_2; + if (rank != 2) return TREXIO_INVALID_ARG_3; + if (dims == NULL) return TREXIO_INVALID_ARG_4; if (list == NULL) return TREXIO_INVALID_ARG_5; const char determinant_list_file_name[256] = "/determinant_list.txt"; @@ -1733,6 +1780,7 @@ trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file, /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, determinant_list_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name)); @@ -1767,6 +1815,7 @@ trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file, memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH); /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, det_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(det_file_name)); @@ -1795,6 +1844,7 @@ trexio_exit_code trexio_text_has_determinant_list(trexio_t* const file) /* Copy directory name in file_full_path */ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH); + file_full_path[TREXIO_MAX_FILENAME_LENGTH-1] = '\0'; /* Append name of the file with sparse data */ strncat (file_full_path, determinant_list_file_name, TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name)); diff --git a/tests/io_determinant.c b/tests/io_determinant.c index d9973e2d..601b2cd9 100644 --- a/tests/io_determinant.c +++ b/tests/io_determinant.c @@ -5,7 +5,7 @@ #include #define SIZE 100 -#define N_CHUNKS 5 +#define N_CHUNKS 7 #define STATE_TEST 2 static int test_write_determinant (const char* file_name, const back_end_t backend, const int64_t offset, const int mo_num) { @@ -52,7 +52,6 @@ static int test_write_determinant (const char* file_name, const back_end_t backe det_list = (int64_t*) calloc(2 * int_num * SIZE, sizeof(int64_t)); det_coef = (double*) calloc(SIZE, sizeof(double)); - int64_t size_list = TREXIO_NORB_PER_INT * int_num; const int32_t orb_list_up[4] = {0,1,2,3}; const int32_t orb_list_dn[3] = {0,1,2}; @@ -64,7 +63,7 @@ static int test_write_determinant (const char* file_name, const back_end_t backe } // write dataset chunks of sparse data in the file (including FAKE statements) - uint64_t chunk_size = (uint64_t) SIZE/N_CHUNKS; + uint64_t chunk_size = (uint64_t) (SIZE-1)/N_CHUNKS+1; uint64_t offset_f = 0UL; uint64_t offset_d = 0UL; if (offset != 0L) offset_f += offset; @@ -77,7 +76,10 @@ static int test_write_determinant (const char* file_name, const back_end_t backe // write n_chunks times using write_sparse for(int i=0; i SIZE) { + chunk_size = SIZE % chunk_size; + } + //printf("chunk_size: %ld | %ld\n", chunk_size, offset_f+chunk_size); rc = trexio_write_determinant_list(file, offset_f, chunk_size, &det_list[2*int_num*offset_d]); assert(rc == TREXIO_SUCCESS); @@ -174,7 +176,7 @@ static int test_read_determinant (const char* file_name, const back_end_t backen int64_t* det_list_read; double* det_coef_read; double check_diff; - uint64_t size_r = 40L; + uint64_t size_r = 2*SIZE; det_list_read = (int64_t*) calloc(2*int_num*size_r,sizeof(int64_t)); det_coef_read = (double*) calloc(size_r,sizeof(double)); @@ -190,7 +192,7 @@ static int test_read_determinant (const char* file_name, const back_end_t backen if (offset != 0L) offset_file_read += offset; // read one chunk using the aforementioned parameters - printf("int_num: %d\n", int_num); + //printf("int_num: %d\n", int_num); rc = trexio_read_determinant_list(file, offset_file_read, &chunk_read, &det_list_read[2*int_num*offset_data_read]); assert(rc == TREXIO_SUCCESS); assert(chunk_read == read_size_check); @@ -230,6 +232,8 @@ static int test_read_determinant (const char* file_name, const back_end_t backen } */ assert(rc == TREXIO_END); + //printf("%d %d\n", (int) chunk_read, (int) eof_read_size_check); + //fflush(stdout); assert(chunk_read == eof_read_size_check); chunk_read = read_size_check; @@ -248,11 +252,11 @@ static int test_read_determinant (const char* file_name, const back_end_t backen assert(check_diff*check_diff < 1e-14); // check the value of determinant_num - int32_t det_num = 0; - int32_t size_check = SIZE; + int64_t det_num = 0; + int64_t size_check = SIZE; if (offset != 0L) size_check += offset; - rc = trexio_read_determinant_num(file, &det_num); + rc = trexio_read_determinant_num_64(file, &det_num); assert(rc == TREXIO_SUCCESS); assert(det_num == size_check); @@ -262,7 +266,28 @@ static int test_read_determinant (const char* file_name, const back_end_t backen int32_t* orb_list_dn = (int32_t*) calloc(size_list, sizeof(int32_t)); int32_t occ_num_up, occ_num_dn; - rc = trexio_read_determinant_list(file, 0L, &chunk_read, &det_list_read[0L]); +// rc = trexio_read_determinant_list(file, 0L, &chunk_read, &det_list_read[0L]); + // read n_chunks times using read_sparse + int64_t chunk_size = (int64_t) (SIZE-1)/N_CHUNKS+1; + uint64_t offset_f = 0UL; + uint64_t offset_d = 0UL; + for(int i=0; i SIZE) { + chunk_size = SIZE % chunk_size; + } +*/ + //printf("chunk_size: %ld | %ld\n", chunk_size, offset_f+chunk_size); + rc = trexio_read_determinant_list(file, offset_f, &chunk_size, &det_list_read[2*int_num*offset_d]); + assert(rc == TREXIO_SUCCESS || rc == TREXIO_END); + + rc = trexio_read_determinant_coefficient(file, offset_f, &chunk_size, &det_coef_read[offset_d]); + assert(rc == TREXIO_SUCCESS || rc == TREXIO_END); + + offset_d += chunk_size; + offset_f += chunk_size; + } + assert (rc == TREXIO_SUCCESS); rc = trexio_to_orbital_list_up_dn (int_num, &det_list_read[0], orb_list_up, orb_list_dn, &occ_num_up, &occ_num_dn); diff --git a/tests/io_dset_sparse.c b/tests/io_dset_sparse.c index 4b196721..96025705 100644 --- a/tests/io_dset_sparse.c +++ b/tests/io_dset_sparse.c @@ -23,12 +23,12 @@ static int test_write_dset_sparse (const char* file_name, const back_end_t backe // parameters to be written int32_t* index; double* value; - int64_t size = mo_num/2; + uint64_t size = mo_num/2; index = calloc(4L*size, sizeof(int32_t)); value = calloc(size, sizeof(double)); - for(int i=0; i 0 ? chunk_size : (uint64_t) size; - int n_chunks = size/chunk_size; - printf("chunk_size = %ld\n", (long) chunk_size); - printf("n_chunks = %d\n", n_chunks); uint64_t offset_f = 0UL + offset; uint64_t offset_d = 0UL; @@ -55,10 +52,10 @@ static int test_write_dset_sparse (const char* file_name, const back_end_t backe // write n_chunks times using write_sparse while(offset_d < size) { if (offset_d+chunk_size > size) chunk_size = size-offset_d; - printf("chunk_size = %ld\n", (long) chunk_size); + //printf("chunk_size = %ld\n", (long) chunk_size); if (chunk_size == 0L) break; rc = trexio_write_mo_2e_int_eri(file, offset_f, chunk_size, &index[4*offset_d], &value[offset_d]); - printf("%5d: %s\n", __LINE__, trexio_string_of_error(rc)); + //printf("%5d: %s\n", __LINE__, trexio_string_of_error(rc)); assert(rc == TREXIO_SUCCESS); offset_d += chunk_size; offset_f += chunk_size; @@ -137,7 +134,7 @@ static int test_read_dset_sparse (const char* file_name, const back_end_t backen int32_t mo_num = 0; rc = trexio_read_mo_num(file, &mo_num); assert(rc == TREXIO_SUCCESS); - printf("%5d: mo_num = %d\n", __LINE__, mo_num); + //printf("%5d: mo_num = %d\n", __LINE__, mo_num); const int64_t size = mo_num/2; // define arrays to read into @@ -160,7 +157,7 @@ static int test_read_dset_sparse (const char* file_name, const back_end_t backen // read one chunk using the aforementioned parameters rc = trexio_read_mo_2e_int_eri(file, offset_file_read, &chunk_read, &index_read[0], &value_read[0]); - printf("%5d: %s\n", __LINE__, trexio_string_of_error(rc)); + //printf("%5d: %s\n", __LINE__, trexio_string_of_error(rc)); /* for (int i=0 ; i +#include #include #include #include @@ -119,25 +120,25 @@ static int test_read_jastrow (const char* file_name, const back_end_t backend) { double ee [2] = { 0., 0. }; rc = trexio_read_jastrow_ee(file, ee); assert (rc == TREXIO_SUCCESS); - assert (ee[0] == 0.5); - assert (ee[1] == 2.0); + assert (fabs(ee[0]-0.5) < 1.e-15); + assert (fabs(ee[1]-2.0) < 1.e-15); double en [3] = { 0., 0., 0. }; rc = trexio_read_jastrow_en(file, en); assert (rc == TREXIO_SUCCESS); - assert (en[0] == 1.0); - assert (en[1] == 2.0); - assert (en[2] == 3.0); + assert (fabs(en[0]-1.0) < 1.e-15); + assert (fabs(en[1]-2.0) < 1.e-15); + assert (fabs(en[2]-3.0) < 1.e-15); double een [6]; rc = trexio_read_jastrow_een(file, een); assert (rc == TREXIO_SUCCESS); - assert (een[0] == 11.0); - assert (een[1] == 12.0); - assert (een[2] == 13.0); - assert (een[3] == 14.0); - assert (een[4] == 15.0); - assert (een[5] == 16.0); + assert (fabs(een[0]-11.0) < 1.e-15); + assert (fabs(een[1]-12.0) < 1.e-15); + assert (fabs(een[2]-13.0) < 1.e-15); + assert (fabs(een[3]-14.0) < 1.e-15); + assert (fabs(een[4]-15.0) < 1.e-15); + assert (fabs(een[5]-16.0) < 1.e-15); int en_nucleus [3] = { 0, 0, 0 }; rc = trexio_read_jastrow_en_nucleus(file, en_nucleus); @@ -159,14 +160,14 @@ static int test_read_jastrow (const char* file_name, const back_end_t backend) { double ee_scaling = 0.0; rc = trexio_read_jastrow_ee_scaling(file, &ee_scaling); assert (rc == TREXIO_SUCCESS); - assert (ee_scaling == 1.0); + assert (fabs(ee_scaling-1.0) < 1.e-15); double en_scaling[3] = { 0.5, 1.0, 0.5 }; rc = trexio_read_jastrow_en_scaling(file, en_scaling); assert (rc == TREXIO_SUCCESS); - assert (en_scaling[0] == 0.5); - assert (en_scaling[1] == 1.0); - assert (en_scaling[2] == 0.5); + assert (fabs(en_scaling[0]-0.5) < 1.e-15); + assert (fabs(en_scaling[1]-1.0) < 1.e-15); + assert (fabs(en_scaling[2]-0.5) < 1.e-15); rc = trexio_close(file); /*================= END OF TEST ==================*/ diff --git a/tests/open.c b/tests/open.c index db0bba76..3d0ac198 100644 --- a/tests/open.c +++ b/tests/open.c @@ -117,7 +117,7 @@ static int test_open_errors (const back_end_t backend) { } -static int test_inquire (const back_end_t backend) { +static int test_inquire () { /* Try to call trexio_inquire function */ @@ -151,7 +151,7 @@ int main(void) { test_open_r (TREXIO_FILE, TEST_BACKEND); test_open_auto (TREXIO_FILE); test_open_errors(TEST_BACKEND); - test_inquire (TEST_BACKEND); + test_inquire (); rc = system(RM_COMMAND); assert (rc == 0); diff --git a/tests/overwrite_all.c b/tests/overwrite_all.c index b2236d7e..d69decca 100644 --- a/tests/overwrite_all.c +++ b/tests/overwrite_all.c @@ -170,7 +170,7 @@ static int test_overwrite_safe (const char* file_name, const back_end_t backend) } -int test_read(const char* file_name, const back_end_t backend) { +static int test_read(const char* file_name, const back_end_t backend) { /*========= Test read ===========*/ diff --git a/tests/run_valgrind.sh b/tests/run_valgrind.sh new file mode 100755 index 00000000..7c2c4058 --- /dev/null +++ b/tests/run_valgrind.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -e + +TESTS_C="\ + io_all \ + open_text \ + io_num_text \ + io_dset_float_text \ + io_dset_int_text \ + io_dset_sparse_text \ + io_determinant_text \ + io_jastrow_text \ + io_safe_dset_float_text \ + io_str_text \ + io_dset_str_text \ + delete_group_text \ + overwrite_all_text \ + pre_close \ + open_hdf5 \ + io_num_hdf5 \ + io_dset_float_hdf5 \ + io_dset_int_hdf5 \ + io_dset_sparse_hdf5 \ + io_determinant_hdf5 \ + io_jastrow_hdf5 \ + io_safe_dset_float_hdf5 \ + io_str_hdf5 \ + io_dset_str_hdf5 \ + delete_group_hdf5 \ + overwrite_all_hdf5" + +TESTS="$TESTS_C test_f" + +for test in $TESTS; do + echo "$test" + libtool --mode=execute valgrind \ + --leak-check=full \ + --show-leak-kinds=all \ + --error-exitcode=666 \ + --errors-for-leak-kinds=all \ + --suppressions=valgrind.supp \ + "./$test" +done diff --git a/tests/test_f.f90 b/tests/test_f.f90 index 0b82e101..81ba0c15 100644 --- a/tests/test_f.f90 +++ b/tests/test_f.f90 @@ -327,7 +327,8 @@ subroutine test_read(file_name, back_end) integer(trexio_t) :: trex_file - integer :: i, j, k, ind, offset, flag + integer*8 :: i + integer :: j, k, ind, offset, flag integer(trexio_exit_code) :: rc = 1 integer :: num, num_read, basis_shell_num @@ -659,11 +660,12 @@ subroutine test_read_void(file_name, back_end) integer, intent(in) :: back_end integer(trexio_t) :: trex_file - integer :: rc = 1 - character(128) :: str + integer :: rc + character*(128) :: str ! ================= START OF TEST ===================== ! + rc = TREXIO_SUCCESS trex_file = trexio_open(file_name, 'r', back_end, rc) if (rc /= TREXIO_OPEN_ERROR) then rc = trexio_close(trex_file) diff --git a/tests/valgrind.supp b/tests/valgrind.supp new file mode 100644 index 00000000..9ede9f0c --- /dev/null +++ b/tests/valgrind.supp @@ -0,0 +1,84 @@ +{ + supp1 + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + fun:H5TS_cancel_count_inc + fun:H5check_version + fun:trexio_hdf5_init + fun:trexio_open + fun:test_* + fun:main +} +{ + supp2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + obj:/usr/lib/x86_64-linux-gnu/libhdf5_serial.so.103.3.0 + obj:/usr/lib/x86_64-linux-gnu/libhdf5_serial.so.103.3.0 + fun:H5CX_push + fun:H5Fcreate + fun:trexio_hdf5_init + fun:trexio_open + fun:test_* + fun:main +} +{ + supp3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:H5E__get_stack + fun:H5E_clear_stack + fun:H5Fcreate + fun:trexio_hdf5_init + fun:trexio_open + fun:test_* + fun:main +} +{ + fortsupp1 + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + fun:H5TS_cancel_count_inc + fun:H5check_version + fun:trexio_hdf5_init + fun:trexio_open + fun:__trexio_MOD_trexio_open + fun:test_write_ + fun:MAIN__ + fun:main +} +{ + fortsupp2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + obj:/usr/lib/x86_64-linux-gnu/libhdf5_serial.so.103.3.0 + obj:/usr/lib/x86_64-linux-gnu/libhdf5_serial.so.103.3.0 + fun:H5CX_push + fun:H5Fcreate + fun:trexio_hdf5_init + fun:trexio_open + fun:__trexio_MOD_trexio_open + fun:test_write_ + fun:MAIN__ + fun:main +} +{ + fortsupp3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:H5E__get_stack + fun:H5E_clear_stack + fun:H5Fcreate + fun:trexio_hdf5_init + fun:trexio_open + fun:__trexio_MOD_trexio_open + fun:test_write_ + fun:MAIN__ + fun:main +}