matio icon indicating copy to clipboard operation
matio copied to clipboard

saving structure in v7 format with compression

Open SciCed opened this issue 1 year ago • 4 comments
trafficstars

Saving a structure in v7 format with compression creates a corrupted file. After some investigation, the problem seems to be present since matio 1.5.12.

File generated with matio 1.5.9 (not corrupted): structS-matio-1.5.9.zip

File generated with matio 1.5.27 (corrupted): structS-matio-1.5.27.zip

The structure saved contains two fields type and age with values "logiciel" and 30.

SciCed avatar Jun 13 '24 14:06 SciCed

Thanks for reporting. That's rather unexpected given the age of v1.5.12. Can you share the code how you created the MAT files? Did you run git bisect to find the bad commit?

tbeu avatar Jun 13 '24 18:06 tbeu

I did not use git bisect, I rebuilt matio on different tags to find the last working version. The Scilab code used to generate files:

structS = struct("type", "logiciel", "age", 30);
savematfile("structS-matio-1.5.9.mat", "structS", "-v7")

Files generated using matio 1.5.9 can be read back in 1.5.9 or 1.5.27 but files generated using 1.5.27 cannot be read in 1.5.9 nor 1.5.27, that is why I incriminated the save.

Without compression, I can save and load files without trouble. I hope this helps.

SciCed avatar Jun 14 '24 08:06 SciCed

Thanks for the details! Do you mind to run git bisect to find the bad commit as in your other issue? I do hope that it will be easier for you than guessing by me because of the many changes between 1.5.9 and 1.5.12. Thank you!

tbeu avatar Jun 15 '24 07:06 tbeu

I am afraid I cannot reproduce without the driving Scilab code. The following vanilla Matio test code produces a 100% binary identical MAT file to your valid structS-matio-1.5.9.mat - tested with current abe00b806aaab19938805f4b66b3d62a28d1cf4a on Win (little endian) with MSVC.

mat_t *mat;
char output_name[256];
int version[3];

Mat_GetLibraryVersion(version, version + 1, version + 2);
snprintf(output_name, 256, "structS-matio-%d.%d.%d.mat", version[0], version[1], version[2]);

mat = Mat_CreateVer(output_name, "MATLAB 5.0 MAT-file, Platform: x86_64-pc-windows, Created by: libmatio v1.5.9 on Thu Jun 13 16:06:30 2024\x0A", MAT_FT_MAT5);
if (mat) {
  const wchar_t *str = L"logiciel";
  const double age[1] = { 30.0 };
  const size_t num_fields = 2;
  const char *fieldnames[2] = { "type", "age" };
  size_t dims[2];
  matvar_t *matvar, *struct_matvar;
  
  dims[0] = 1; dims[1] = 1;
  struct_matvar = Mat_VarCreateStruct("structS", 2, dims, fieldnames, num_fields);
  dims[0] = 1; dims[1] = 8;
  matvar = Mat_VarCreate(fieldnames[0], MAT_C_CHAR, MAT_T_UINT16, 2, dims, (void *)str, 0);
  Mat_VarSetStructFieldByName(struct_matvar, fieldnames[0], 0, matvar);
  dims[0] = 1; dims[1] = 1;
  matvar = Mat_VarCreate(fieldnames[1], MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, (void *)age, 0);
  Mat_VarSetStructFieldByName(struct_matvar, fieldnames[1], 0, matvar);
  Mat_VarWrite(mat, struct_matvar, MAT_COMPRESSION_ZLIB);
  Mat_VarFree(struct_matvar);
  Mat_Close(mat);
}

tbeu avatar Jul 16 '24 20:07 tbeu

Thanks for having a look. I've built your code and the generated file can be loaded in Scilab. I'll check what's the difference between your code and what we are doing in Scilab.

SciCed avatar Aug 28 '24 14:08 SciCed

Here is a code, based on yours, that reproduces what we are doing in Scilab. The problem occurred when I changed the string logiciel from wchar_t* to char* and MAT_T_UINT8 to MAT_T_UINT16.

    mat_t *mat;
    char output_name[256];
    int version[3];

    Mat_GetLibraryVersion(version, version + 1, version + 2);
    snprintf(output_name, 256, "structS-matio-%d.%d.%d.mat", version[0], version[1], version[2]);

    mat = Mat_CreateVer(output_name, "MATLAB 5.0 MAT-file, Platform: x86_64-pc-windows, Created by: libmatio v1.5.9 on Thu Jun 13 16:06:30 2024\x0A", MAT_FT_MAT5);
    if (mat) {
        const char* str = "logiciel";
        const double age[1] = { 30.0 };
        const size_t num_fields = 2;
        const char *fieldnames[2] = { "type", "age" };
        size_t dims[2];
        matvar_t *matvar, *struct_matvar;
        matvar_t* structEntries[3] = {NULL, NULL, NULL};

        dims[0] = 1; dims[1] = 8;
        structEntries[0] = Mat_VarCreate(fieldnames[0], MAT_C_CHAR, MAT_T_UINT8, 2, dims, (void *)str, 0);
        dims[0] = 1; dims[1] = 1;
        structEntries[1] = Mat_VarCreate(fieldnames[1], MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, (void *)age, 0);
        dims[0] = 1; dims[1] = 1;
        struct_matvar = Mat_VarCreate("structS", MAT_C_STRUCT, MAT_T_STRUCT, 2, dims, structEntries, 0);

        Mat_VarWrite(mat, struct_matvar, MAT_COMPRESSION_ZLIB);
        Mat_VarFree(struct_matvar);
        Mat_Close(mat);
    }

SciCed avatar Aug 29 '24 08:08 SciCed

Thanks for the test. 6321cda851e4153be6da08e5d0f0d4f92ef20db4 (on mat5.c) seems to be the suspicious commit. Need to investigate in more detail.

tbeu avatar Aug 29 '24 20:08 tbeu

@SciCed Please confirm that 8407b4ef9610eb19ae2d3792d12f5b8ea0663100 fixes the issue.

tbeu avatar Sep 05 '24 17:09 tbeu

@tbeu The fix is working well, thanks!

SciCed avatar Sep 11 '24 09:09 SciCed