From 6ccb802c673e10d2f84d9e96c3afe60d3d963ff2 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Fri, 3 Dec 2021 09:38:55 -0500 Subject: [PATCH 1/9] Fix pre-1900 date bug #367 and add test. --- src/libmdb/data.c | 64 +++++++++++++++++++++++------------------------ test_script.sh | 1 + 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 5b5668b..bb87a6d 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -23,7 +23,7 @@ #define OFFSET_MASK 0x1fff #define OLE_BUFFER_SIZE (MDB_BIND_SIZE*64) -static int _mdb_attempt_bind(MdbHandle *mdb, +static int _mdb_attempt_bind(MdbHandle *mdb, MdbColumn *col, unsigned char isnull, int offset, int len); static char *mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start); #ifdef MDB_COPY_OLE @@ -91,8 +91,8 @@ int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_pt if (!table->columns) return -1; - /* - ** the column arrary is 0 based, so decrement to get 1 based parameter + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter */ col_num--; @@ -121,7 +121,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int if (!table->columns) return -1; - + for (i=0;inum_cols;i++) { col=g_ptr_array_index(table->columns,i); if (!g_ascii_strcasecmp(col->name,col_name)) { @@ -144,7 +144,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int * @buf: Pointer for returning a pointer to the page * @off: Pointer for returning an offset to the row * @len: Pointer for returning the length of the row - * + * * Returns: 0 on success. -1 on failure. */ int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len) @@ -183,7 +183,7 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len) return 0; } -int +int mdb_find_end_of_row(MdbHandle *mdb, int row) { int rco = mdb->fmt->row_count_offset; @@ -226,9 +226,9 @@ int bit_num = (col_num - 1) % 8; return 1; } } -/* bool has to be handled specially because it uses the null bit to store its +/* bool has to be handled specially because it uses the null bit to store its ** value*/ -static size_t +static size_t mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) { col->cur_value_len = value; @@ -338,11 +338,11 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) if (row_start & 0x4000) delflag++; row_start &= OFFSET_MASK; /* remove flags */ #if MDB_DEBUG - fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", row, row_start, row_start + row_size - 1, lookupflag ? "[lookup]" : "", delflag ? "[delflag]" : ""); -#endif +#endif if (!table->noskip_del && delflag) { return 0; @@ -355,10 +355,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) free(fields); return 0; } - + #if MDB_DEBUG fprintf(stdout,"sarg test passed row %d \n", row); -#endif +#endif #if MDB_DEBUG mdb_buffer_dump(mdb->pg_buf, row_start, row_size); @@ -376,10 +376,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) return 1; } -static int _mdb_attempt_bind(MdbHandle *mdb, - MdbColumn *col, - unsigned char isnull, - int offset, +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, int len) { if (col->col_type == MDB_BOOL) { @@ -431,7 +431,7 @@ int mdb_read_next_dpg(MdbTableDef *table) next_pg, mdb->pg_buf[0], mdb_get_int32(mdb->pg_buf, 4), entry->table_pg); } fprintf(stderr, "Warning: defaulting to brute force read\n"); -#endif +#endif /* can't do a fast read, go back to the old way */ do { if (!mdb_read_pg(mdb, table->cur_phys_pg++)) @@ -448,7 +448,7 @@ int mdb_rewind_table(MdbTableDef *table) return 0; } -int +int mdb_fetch_row(MdbTableDef *table) { MdbHandle *mdb = table->entry->mdb; @@ -482,7 +482,7 @@ mdb_fetch_row(MdbTableDef *table) g_ptr_array_index(pages, table->cur_pg_num-1), fmt->pg_size); } else if (table->strategy==MDB_INDEX_SCAN) { - + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { mdb_index_scan_free(table); return 0; @@ -494,7 +494,7 @@ mdb_fetch_row(MdbTableDef *table) /* if at end of page, find a new data page */ if (table->cur_row >= rows) { table->cur_row=0; - + if (!mdb_read_next_dpg(table)) { return 0; } @@ -542,7 +542,7 @@ int mdb_is_fixed_col(MdbColumn *col) return col->is_fixed; } #if 0 -static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) { int i; @@ -560,7 +560,7 @@ int i; * responsible for not calling this function. Then, it doesn't have to * preserve the original value. */ -size_t +size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { guint32 ole_len; @@ -595,7 +595,7 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) return len - 4; } -size_t +size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) { guint32 ole_len; @@ -648,7 +648,7 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) } mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); - if (col->bind_ptr) + if (col->bind_ptr) memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); col->cur_blob_pg_row = mdb_get_int32(buf, row_start); mdb_debug(MDB_DEBUG_OLE, "next pg_row %d", col->cur_blob_pg_row); @@ -704,7 +704,7 @@ static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size) if (size 1e6) // About 2700 AD - return; + // if (td < 0.0 || td > 1e6) // About 2700 AD + // return; yr = 1; day = (long)(td); @@ -978,7 +978,7 @@ int floor_log10(double f, int is_single) if (f < 0.0) f = -f; - + if ((f == 0.0) || (f == 1.0) || isinf(f)) { return 0; } else if (f < 1.0) { @@ -1096,7 +1096,7 @@ int mdb_col_disp_size(MdbColumn *col) return 20; break; case MDB_MEMO: - return 64000; + return 64000; break; case MDB_MONEY: return 21; @@ -1136,7 +1136,7 @@ int mdb_col_fixed_size(MdbColumn *col) return -1; break; case MDB_MEMO: - return -1; + return -1; break; case MDB_MONEY: return 8; diff --git a/test_script.sh b/test_script.sh index 083fef9..ede5db2 100755 --- a/test_script.sh +++ b/test_script.sh @@ -16,3 +16,4 @@ ./src/util/mdb-ver test/data/ASampleDatabase.accdb ./src/util/mdb-ver test/data/nwind.mdb ./src/util/mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner +./src/util/mdb-export -X '@' -d '|' -D %F -T '%F %T' -R "\n" -q '"' -H -e test/data/DateTestDatabase.mdb DateTest \ No newline at end of file From 0a012235e82bc667cf3b6ce5da87a3d71dcbf764 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Fri, 3 Dec 2021 11:30:28 -0500 Subject: [PATCH 2/9] Ignore the test directory. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9843633..f354f78 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ m4/ !m4/ccalias.m4 !m4/iconv.m4 !m4/readline.m4 +/test/ config.log config.status configure From c6ab656741c6d2be4c6708dd9f8905830c6c255e Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Fri, 3 Dec 2021 11:33:27 -0500 Subject: [PATCH 3/9] Undo whitespace changes, add comment. --- src/libmdb/data.c | 62 ++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index bb87a6d..5412e11 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -23,7 +23,7 @@ #define OFFSET_MASK 0x1fff #define OLE_BUFFER_SIZE (MDB_BIND_SIZE*64) -static int _mdb_attempt_bind(MdbHandle *mdb, +static int _mdb_attempt_bind(MdbHandle *mdb, MdbColumn *col, unsigned char isnull, int offset, int len); static char *mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start); #ifdef MDB_COPY_OLE @@ -91,8 +91,8 @@ int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_pt if (!table->columns) return -1; - /* - ** the column arrary is 0 based, so decrement to get 1 based parameter + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter */ col_num--; @@ -121,7 +121,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int if (!table->columns) return -1; - + for (i=0;inum_cols;i++) { col=g_ptr_array_index(table->columns,i); if (!g_ascii_strcasecmp(col->name,col_name)) { @@ -144,7 +144,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int * @buf: Pointer for returning a pointer to the page * @off: Pointer for returning an offset to the row * @len: Pointer for returning the length of the row - * + * * Returns: 0 on success. -1 on failure. */ int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len) @@ -183,7 +183,7 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len) return 0; } -int +int mdb_find_end_of_row(MdbHandle *mdb, int row) { int rco = mdb->fmt->row_count_offset; @@ -226,9 +226,9 @@ int bit_num = (col_num - 1) % 8; return 1; } } -/* bool has to be handled specially because it uses the null bit to store its +/* bool has to be handled specially because it uses the null bit to store its ** value*/ -static size_t +static size_t mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) { col->cur_value_len = value; @@ -338,11 +338,11 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) if (row_start & 0x4000) delflag++; row_start &= OFFSET_MASK; /* remove flags */ #if MDB_DEBUG - fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", row, row_start, row_start + row_size - 1, lookupflag ? "[lookup]" : "", delflag ? "[delflag]" : ""); -#endif +#endif if (!table->noskip_del && delflag) { return 0; @@ -355,10 +355,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) free(fields); return 0; } - + #if MDB_DEBUG fprintf(stdout,"sarg test passed row %d \n", row); -#endif +#endif #if MDB_DEBUG mdb_buffer_dump(mdb->pg_buf, row_start, row_size); @@ -376,10 +376,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) return 1; } -static int _mdb_attempt_bind(MdbHandle *mdb, - MdbColumn *col, - unsigned char isnull, - int offset, +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, int len) { if (col->col_type == MDB_BOOL) { @@ -431,7 +431,7 @@ int mdb_read_next_dpg(MdbTableDef *table) next_pg, mdb->pg_buf[0], mdb_get_int32(mdb->pg_buf, 4), entry->table_pg); } fprintf(stderr, "Warning: defaulting to brute force read\n"); -#endif +#endif /* can't do a fast read, go back to the old way */ do { if (!mdb_read_pg(mdb, table->cur_phys_pg++)) @@ -448,7 +448,7 @@ int mdb_rewind_table(MdbTableDef *table) return 0; } -int +int mdb_fetch_row(MdbTableDef *table) { MdbHandle *mdb = table->entry->mdb; @@ -482,7 +482,7 @@ mdb_fetch_row(MdbTableDef *table) g_ptr_array_index(pages, table->cur_pg_num-1), fmt->pg_size); } else if (table->strategy==MDB_INDEX_SCAN) { - + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { mdb_index_scan_free(table); return 0; @@ -494,7 +494,7 @@ mdb_fetch_row(MdbTableDef *table) /* if at end of page, find a new data page */ if (table->cur_row >= rows) { table->cur_row=0; - + if (!mdb_read_next_dpg(table)) { return 0; } @@ -542,7 +542,7 @@ int mdb_is_fixed_col(MdbColumn *col) return col->is_fixed; } #if 0 -static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) { int i; @@ -560,7 +560,7 @@ int i; * responsible for not calling this function. Then, it doesn't have to * preserve the original value. */ -size_t +size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { guint32 ole_len; @@ -595,7 +595,7 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) return len - 4; } -size_t +size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) { guint32 ole_len; @@ -648,7 +648,7 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) } mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); - if (col->bind_ptr) + if (col->bind_ptr) memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); col->cur_blob_pg_row = mdb_get_int32(buf, row_start); mdb_debug(MDB_DEBUG_OLE, "next pg_row %d", col->cur_blob_pg_row); @@ -704,7 +704,7 @@ static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size) if (size 1e6) // About 2700 AD // return; @@ -978,7 +980,7 @@ int floor_log10(double f, int is_single) if (f < 0.0) f = -f; - + if ((f == 0.0) || (f == 1.0) || isinf(f)) { return 0; } else if (f < 1.0) { @@ -1096,7 +1098,7 @@ int mdb_col_disp_size(MdbColumn *col) return 20; break; case MDB_MEMO: - return 64000; + return 64000; break; case MDB_MONEY: return 21; @@ -1136,7 +1138,7 @@ int mdb_col_fixed_size(MdbColumn *col) return -1; break; case MDB_MEMO: - return -1; + return -1; break; case MDB_MONEY: return 8; From 898e880e875dee4c2555e6f75792b50fa6fc3973 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Fri, 3 Dec 2021 15:23:31 -0500 Subject: [PATCH 4/9] Retain a limit on both ends, mark where we might return a null instead. --- src/libmdb/data.c | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 5412e11..6850fab 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -23,7 +23,7 @@ #define OFFSET_MASK 0x1fff #define OLE_BUFFER_SIZE (MDB_BIND_SIZE*64) -static int _mdb_attempt_bind(MdbHandle *mdb, +static int _mdb_attempt_bind(MdbHandle *mdb, MdbColumn *col, unsigned char isnull, int offset, int len); static char *mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start); #ifdef MDB_COPY_OLE @@ -91,8 +91,8 @@ int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_pt if (!table->columns) return -1; - /* - ** the column arrary is 0 based, so decrement to get 1 based parameter + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter */ col_num--; @@ -121,7 +121,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int if (!table->columns) return -1; - + for (i=0;inum_cols;i++) { col=g_ptr_array_index(table->columns,i); if (!g_ascii_strcasecmp(col->name,col_name)) { @@ -144,7 +144,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int * @buf: Pointer for returning a pointer to the page * @off: Pointer for returning an offset to the row * @len: Pointer for returning the length of the row - * + * * Returns: 0 on success. -1 on failure. */ int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len) @@ -183,7 +183,7 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len) return 0; } -int +int mdb_find_end_of_row(MdbHandle *mdb, int row) { int rco = mdb->fmt->row_count_offset; @@ -226,9 +226,9 @@ int bit_num = (col_num - 1) % 8; return 1; } } -/* bool has to be handled specially because it uses the null bit to store its +/* bool has to be handled specially because it uses the null bit to store its ** value*/ -static size_t +static size_t mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) { col->cur_value_len = value; @@ -338,11 +338,11 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) if (row_start & 0x4000) delflag++; row_start &= OFFSET_MASK; /* remove flags */ #if MDB_DEBUG - fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", row, row_start, row_start + row_size - 1, lookupflag ? "[lookup]" : "", delflag ? "[delflag]" : ""); -#endif +#endif if (!table->noskip_del && delflag) { return 0; @@ -355,10 +355,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) free(fields); return 0; } - + #if MDB_DEBUG fprintf(stdout,"sarg test passed row %d \n", row); -#endif +#endif #if MDB_DEBUG mdb_buffer_dump(mdb->pg_buf, row_start, row_size); @@ -376,10 +376,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) return 1; } -static int _mdb_attempt_bind(MdbHandle *mdb, - MdbColumn *col, - unsigned char isnull, - int offset, +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, int len) { if (col->col_type == MDB_BOOL) { @@ -431,7 +431,7 @@ int mdb_read_next_dpg(MdbTableDef *table) next_pg, mdb->pg_buf[0], mdb_get_int32(mdb->pg_buf, 4), entry->table_pg); } fprintf(stderr, "Warning: defaulting to brute force read\n"); -#endif +#endif /* can't do a fast read, go back to the old way */ do { if (!mdb_read_pg(mdb, table->cur_phys_pg++)) @@ -448,7 +448,7 @@ int mdb_rewind_table(MdbTableDef *table) return 0; } -int +int mdb_fetch_row(MdbTableDef *table) { MdbHandle *mdb = table->entry->mdb; @@ -482,7 +482,7 @@ mdb_fetch_row(MdbTableDef *table) g_ptr_array_index(pages, table->cur_pg_num-1), fmt->pg_size); } else if (table->strategy==MDB_INDEX_SCAN) { - + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { mdb_index_scan_free(table); return 0; @@ -494,7 +494,7 @@ mdb_fetch_row(MdbTableDef *table) /* if at end of page, find a new data page */ if (table->cur_row >= rows) { table->cur_row=0; - + if (!mdb_read_next_dpg(table)) { return 0; } @@ -542,7 +542,7 @@ int mdb_is_fixed_col(MdbColumn *col) return col->is_fixed; } #if 0 -static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) { int i; @@ -560,7 +560,7 @@ int i; * responsible for not calling this function. Then, it doesn't have to * preserve the original value. */ -size_t +size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { guint32 ole_len; @@ -595,7 +595,7 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) return len - 4; } -size_t +size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) { guint32 ole_len; @@ -648,7 +648,7 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) } mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); - if (col->bind_ptr) + if (col->bind_ptr) memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); col->cur_blob_pg_row = mdb_get_int32(buf, row_start); mdb_debug(MDB_DEBUG_OLE, "next pg_row %d", col->cur_blob_pg_row); @@ -704,7 +704,7 @@ static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size) if (size 1e6) // About 2700 AD - // return; + // limit to ~1100AD--2700A to protect from overflow + if (td < -1e6 || td > 1e6) + return; yr = 1; day = (long)(td); @@ -947,6 +946,8 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start) mdb_date_to_tm(td, &t); + // check if t is still unchanged, return empty string? + strftime(text, mdb->bind_size, mdb->date_fmt, &t); return text; @@ -980,7 +981,7 @@ int floor_log10(double f, int is_single) if (f < 0.0) f = -f; - + if ((f == 0.0) || (f == 1.0) || isinf(f)) { return 0; } else if (f < 1.0) { @@ -1098,7 +1099,7 @@ int mdb_col_disp_size(MdbColumn *col) return 20; break; case MDB_MEMO: - return 64000; + return 64000; break; case MDB_MONEY: return 21; @@ -1138,7 +1139,7 @@ int mdb_col_fixed_size(MdbColumn *col) return -1; break; case MDB_MEMO: - return -1; + return -1; break; case MDB_MONEY: return 8; From 57cd54f654f6bffa36bfc8cd2865c45abeb73152 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Fri, 3 Dec 2021 15:35:51 -0500 Subject: [PATCH 5/9] Better idea, return empty string at mdb_date_to_string(). --- src/libmdb/data.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 6850fab..b2f1de1 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -894,10 +894,6 @@ mdb_date_to_tm(double td, struct tm *t) long yr, q; const int *cal; - // limit to ~1100AD--2700A to protect from overflow - if (td < -1e6 || td > 1e6) - return; - yr = 1; day = (long)(td); time = (long)((td - day) * 86400.0 + 0.5); @@ -944,9 +940,11 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start) char *text = g_malloc(mdb->bind_size); double td = mdb_get_double(buf, start); - mdb_date_to_tm(td, &t); + // limit to ~1100AD--2700A to protect from overflow + if (td < -1e6 || td > 1e6) + return strdup(""); - // check if t is still unchanged, return empty string? + mdb_date_to_tm(td, &t); strftime(text, mdb->bind_size, mdb->date_fmt, &t); From 88caaa2004c779e14aa45dc282a56b8005c89e0b Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Mon, 6 Dec 2021 09:44:30 -0500 Subject: [PATCH 6/9] Improve memory allocation following pattern in mdb_col_to_string. --- src/libmdb/data.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index b2f1de1..87f1fb5 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -937,16 +937,20 @@ static char * mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start) { struct tm t = { 0 }; - char *text = g_malloc(mdb->bind_size); + char *text = NULL; double td = mdb_get_double(buf, start); - // limit to ~1100AD--2700A to protect from overflow - if (td < -1e6 || td > 1e6) - return strdup(""); - - mdb_date_to_tm(td, &t); - - strftime(text, mdb->bind_size, mdb->date_fmt, &t); + // limit dates to protect from overflow. + // 1e6 days is ~2700 years, centered at 1900, so this range is: + // Sunday, February 4, 839 BC to Tuesday, November 28, 4637 + if (td < -1e6 || td > 1e6) { + // an "invalid date" would perhaps be better than null (TODO) + text = g_strdup(""); + } else { + text = g_malloc(mdb->bind_size); + mdb_date_to_tm(td, &t); + strftime(text, mdb->bind_size, mdb->date_fmt, &t); + } return text; } From aa4e29f9853f86720e4fcdd147a8b00f25dcce89 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Mon, 6 Dec 2021 10:48:21 -0500 Subject: [PATCH 7/9] Error print. --- src/libmdb/data.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 87f1fb5..029bd07 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -945,11 +945,12 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start) // Sunday, February 4, 839 BC to Tuesday, November 28, 4637 if (td < -1e6 || td > 1e6) { // an "invalid date" would perhaps be better than null (TODO) + // fprintf(stderr, "Warning: mdb_date_to_string called on unsupported date with %f days.\n", td); text = g_strdup(""); } else { text = g_malloc(mdb->bind_size); mdb_date_to_tm(td, &t); - strftime(text, mdb->bind_size, mdb->date_fmt, &t); + strftime(text, mdb->bind_size, fmt, &t); } return text; @@ -1051,9 +1052,6 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int size, text, mdb->bind_size); } break; - case MDB_DATETIME: - text = mdb_date_to_string(mdb, mdb->date_fmt, buf, start); - break; case MDB_MEMO: text = mdb_memo_to_string(mdb, start, size); break; From 7149187745f6b1214424290775c0d790d69c6ce1 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Mon, 6 Dec 2021 11:20:30 -0500 Subject: [PATCH 8/9] Need glib for osx builds with --enable-glib. --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77f9a9d..9bce912 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,7 +49,7 @@ jobs: glib: [ enable-glib, disable-glib ] steps: - name: Install packages - run: brew install bison gawk automake + run: brew install bison gawk automake glib - uses: actions/checkout@v2 - name: Fetch test data run: git clone https://github.com/mdbtools/mdbtestdata.git test @@ -89,7 +89,7 @@ jobs: - name: Remove packages run: brew unlink unixodbc - name: Install packages - run: brew install libiodbc bison gawk automake + run: brew install libiodbc bison gawk automake glib - uses: actions/checkout@v2 - name: Fetch test data run: git clone https://github.com/mdbtools/mdbtestdata.git test From 196bcbfbff9bbbe745b17de7ee6f0c0992fa4b38 Mon Sep 17 00:00:00 2001 From: Andy Reagan Date: Mon, 6 Dec 2021 11:44:36 -0500 Subject: [PATCH 9/9] Remove whitespace changes. --- src/libmdb/data.c | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 029bd07..be59a75 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -23,7 +23,7 @@ #define OFFSET_MASK 0x1fff #define OLE_BUFFER_SIZE (MDB_BIND_SIZE*64) -static int _mdb_attempt_bind(MdbHandle *mdb, +static int _mdb_attempt_bind(MdbHandle *mdb, MdbColumn *col, unsigned char isnull, int offset, int len); static char *mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start); #ifdef MDB_COPY_OLE @@ -91,8 +91,8 @@ int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_pt if (!table->columns) return -1; - /* - ** the column arrary is 0 based, so decrement to get 1 based parameter + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter */ col_num--; @@ -121,7 +121,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int if (!table->columns) return -1; - + for (i=0;inum_cols;i++) { col=g_ptr_array_index(table->columns,i); if (!g_ascii_strcasecmp(col->name,col_name)) { @@ -144,7 +144,7 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int * @buf: Pointer for returning a pointer to the page * @off: Pointer for returning an offset to the row * @len: Pointer for returning the length of the row - * + * * Returns: 0 on success. -1 on failure. */ int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len) @@ -183,7 +183,7 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len) return 0; } -int +int mdb_find_end_of_row(MdbHandle *mdb, int row) { int rco = mdb->fmt->row_count_offset; @@ -226,9 +226,9 @@ int bit_num = (col_num - 1) % 8; return 1; } } -/* bool has to be handled specially because it uses the null bit to store its +/* bool has to be handled specially because it uses the null bit to store its ** value*/ -static size_t +static size_t mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) { col->cur_value_len = value; @@ -338,11 +338,11 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) if (row_start & 0x4000) delflag++; row_start &= OFFSET_MASK; /* remove flags */ #if MDB_DEBUG - fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", row, row_start, row_start + row_size - 1, lookupflag ? "[lookup]" : "", delflag ? "[delflag]" : ""); -#endif +#endif if (!table->noskip_del && delflag) { return 0; @@ -355,10 +355,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) free(fields); return 0; } - + #if MDB_DEBUG fprintf(stdout,"sarg test passed row %d \n", row); -#endif +#endif #if MDB_DEBUG mdb_buffer_dump(mdb->pg_buf, row_start, row_size); @@ -376,10 +376,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) return 1; } -static int _mdb_attempt_bind(MdbHandle *mdb, - MdbColumn *col, - unsigned char isnull, - int offset, +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, int len) { if (col->col_type == MDB_BOOL) { @@ -431,7 +431,7 @@ int mdb_read_next_dpg(MdbTableDef *table) next_pg, mdb->pg_buf[0], mdb_get_int32(mdb->pg_buf, 4), entry->table_pg); } fprintf(stderr, "Warning: defaulting to brute force read\n"); -#endif +#endif /* can't do a fast read, go back to the old way */ do { if (!mdb_read_pg(mdb, table->cur_phys_pg++)) @@ -448,7 +448,7 @@ int mdb_rewind_table(MdbTableDef *table) return 0; } -int +int mdb_fetch_row(MdbTableDef *table) { MdbHandle *mdb = table->entry->mdb; @@ -482,7 +482,7 @@ mdb_fetch_row(MdbTableDef *table) g_ptr_array_index(pages, table->cur_pg_num-1), fmt->pg_size); } else if (table->strategy==MDB_INDEX_SCAN) { - + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { mdb_index_scan_free(table); return 0; @@ -494,7 +494,7 @@ mdb_fetch_row(MdbTableDef *table) /* if at end of page, find a new data page */ if (table->cur_row >= rows) { table->cur_row=0; - + if (!mdb_read_next_dpg(table)) { return 0; } @@ -542,7 +542,7 @@ int mdb_is_fixed_col(MdbColumn *col) return col->is_fixed; } #if 0 -static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) { int i; @@ -560,7 +560,7 @@ int i; * responsible for not calling this function. Then, it doesn't have to * preserve the original value. */ -size_t +size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { guint32 ole_len; @@ -595,7 +595,7 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) return len - 4; } -size_t +size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) { guint32 ole_len; @@ -648,7 +648,7 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size) } mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); - if (col->bind_ptr) + if (col->bind_ptr) memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); col->cur_blob_pg_row = mdb_get_int32(buf, row_start); mdb_debug(MDB_DEBUG_OLE, "next pg_row %d", col->cur_blob_pg_row); @@ -704,7 +704,7 @@ static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size) if (size