1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-01 17:39:21 +03:00
Files
mariadb/storage/archive/ha_archive.h
Monty 031f11717d Fix all warnings given by UBSAN
The easiest way to compile and test the server with UBSAN is to run:
./BUILD/compile-pentium64-ubsan
and then run mysql-test-run.
After this commit, one should be able to run this without any UBSAN
warnings. There is still a few compiler warnings that should be fixed
at some point, but these do not expose any real bugs.

The 'special' cases where we disable, suppress or circumvent UBSAN are:
- ref10 source (as here we intentionally do some shifts that UBSAN
  complains about.
- x86 version of optimized int#korr() methods. UBSAN do not like unaligned
  memory access of integers.  Fixed by using byte_order_generic.h when
  compiling with UBSAN
- We use smaller thread stack with ASAN and UBSAN, which forced me to
  disable a few tests that prints the thread stack size.
- Verifying class types does not work for shared libraries. I added
  suppression in mysql-test-run.pl for this case.
- Added '#ifdef WITH_UBSAN' when using integer arithmetic where it is
  safe to have overflows (two cases, in item_func.cc).

Things fixed:
- Don't left shift signed values
  (byte_order_generic.h, mysqltest.c, item_sum.cc and many more)
- Don't assign not non existing values to enum variables.
- Ensure that bool and enum values are properly initialized in
  constructors.  This was needed as UBSAN checks that these types has
  correct values when one copies an object.
  (gcalc_tools.h, ha_partition.cc, item_sum.cc, partition_element.h ...)
- Ensure we do not called handler functions on unallocated objects or
  deleted objects.
  (events.cc, sql_acl.cc).
- Fixed bugs in Item_sp::Item_sp() where we did not call constructor
  on Query_arena object.
- Fixed several cast of objects to an incompatible class!
  (Item.cc, Item_buff.cc, item_timefunc.cc, opt_subselect.cc, sql_acl.cc,
   sql_select.cc ...)
- Ensure we do not do integer arithmetic that causes over or underflows.
  This includes also ++ and -- of integers.
  (Item_func.cc, Item_strfunc.cc, item_timefunc.cc, sql_base.cc ...)
- Added JSON_VALUE_UNITIALIZED to json_value_types and ensure that
  value_type is initialized to this instead of to -1, which is not a valid
  enum value for json_value_types.
- Ensure we do not call memcpy() when second argument could be null.
- Fixed that Item_func_str::make_empty_result() creates an empty string
  instead of a null string (safer as it ensures we do not do arithmetic
  on null strings).

Other things:

- Changed struct st_position to an OBJECT and added an initialization
  function to it to ensure that we do not copy or use uninitialized
  members. The change to a class was also motived that we used "struct
  st_position" and POSITION randomly trough the code which was
  confusing.
- Notably big rewrite in sql_acl.cc to avoid using deleted objects.
- Changed in sql_partition to use '^' instead of '-'. This is safe as
  the operator is either 0 or 0x8000000000000000ULL.
- Added check for select_nr < INT_MAX in JOIN::build_explain() to
  avoid bug when get_select() could return NULL.
- Reordered elements in POSITION for better alignment.
- Changed sql_test.cc::print_plan() to use pointers instead of objects.
- Fixed bug in find_set() where could could execute '1 << -1'.
- Added variable have_sanitizer, used by mtr.  (This variable was before
  only in 10.5 and up).  It can now have one of two values:
  ASAN or UBSAN.
- Moved ~Archive_share() from ha_archive.cc to ha_archive.h and marked
  it virtual. This was an effort to get UBSAN to work with loaded storage
  engines. I kept the change as the new place is better.
- Added in CONNECT engine COLBLK::SetName(), to get around a wrong cast
  in tabutil.cpp.
- Added HAVE_REPLICATION around usage of rgi_slave, to get embedded
  server to compile with UBSAN. (Patch from Marko).
- Added #ifdef for powerpc64 to avoid a bug in old gcc versions related
  to integer arithmetic.

Changes that should not be needed but had to be done to suppress warnings
from UBSAN:

- Added static_cast<<uint16_t>> around shift to get rid of a LOT of
  compiler warnings when using UBSAN.
- Had to change some '/' of 2 base integers to shift to get rid of
  some compile time warnings.

Reviewed by:
- Json changes: Alexey Botchkov
- Charset changes in ctype-uca.c: Alexander Barkov
- InnoDB changes & Embedded server: Marko Mäkelä
- sql_acl.cc changes: Vicențiu Ciorbaru
- build_explain() changes: Sergey Petrunia
2021-04-20 12:30:09 +03:00

166 lines
6.2 KiB
C++

/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
#include <zlib.h>
#include "azlib.h"
/*
Please read ha_archive.cc first. If you are looking for more general
answers on how storage engines work, look at ha_example.cc and
ha_example.h.
*/
typedef struct st_archive_record_buffer {
uchar *buffer;
uint32 length;
} archive_record_buffer;
class Archive_share : public Handler_share
{
public:
mysql_mutex_t mutex;
THR_LOCK lock;
azio_stream archive_write; /* Archive file we are working with */
ha_rows rows_recorded; /* Number of rows in tables */
char table_name[FN_REFLEN];
char data_file_name[FN_REFLEN];
bool in_optimize;
bool archive_write_open;
bool dirty; /* Flag for if a flush should occur */
bool crashed; /* Meta file is crashed */
Archive_share();
virtual ~Archive_share();
int init_archive_writer();
void close_archive_writer();
int write_v1_metafile();
int read_v1_metafile();
};
/*
Version for file format.
1 - Initial Version (Never Released)
2 - Stream Compression, seperate blobs, no packing
3 - One stream (row and blobs), with packing
*/
#define ARCHIVE_VERSION 3
class ha_archive: public handler
{
THR_LOCK_DATA lock; /* MySQL lock */
Archive_share *share; /* Shared lock info */
azio_stream archive; /* Archive file we are working with */
my_off_t current_position; /* The position of the row we just read */
uchar byte_buffer[IO_SIZE]; /* Initial buffer for our string */
String buffer; /* Buffer used for blob storage */
ha_rows scan_rows; /* Number of rows left in scan */
bool delayed_insert; /* If the insert is delayed */
bool bulk_insert; /* If we are performing a bulk insert */
const uchar *current_key;
uint current_key_len;
uint current_k_offset;
archive_record_buffer *record_buffer;
bool archive_reader_open;
archive_record_buffer *create_record_buffer(unsigned int length);
void destroy_record_buffer(archive_record_buffer *r);
int frm_copy(azio_stream *src, azio_stream *dst);
int frm_compare(azio_stream *src);
unsigned int pack_row_v1(const uchar *record);
public:
ha_archive(handlerton *hton, TABLE_SHARE *table_arg);
~ha_archive()
{
}
const char *index_type(uint inx) { return "NONE"; }
ulonglong table_flags() const
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_STATS_RECORDS_IS_EXACT | HA_CAN_EXPORT |
HA_HAS_RECORDS | HA_CAN_REPAIR | HA_SLOW_RND_POS |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
{
return HA_ONLY_WHOLE_INDEX;
}
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
ulonglong *first_value,
ulonglong *nb_reserved_values);
uint max_supported_keys() const { return 1; }
uint max_supported_key_length() const { return sizeof(ulonglong); }
uint max_supported_key_part_length() const { return sizeof(ulonglong); }
ha_rows records() { return share->rows_recorded; }
int index_init(uint keynr, bool sorted);
virtual int index_read(uchar * buf, const uchar * key,
uint key_len, enum ha_rkey_function find_flag);
virtual int index_read_idx(uchar * buf, uint index, const uchar * key,
uint key_len, enum ha_rkey_function find_flag);
int index_next(uchar * buf);
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(const uchar * buf);
int real_write_row(const uchar *buf, azio_stream *writer);
int truncate();
int rnd_init(bool scan=1);
int rnd_next(uchar *buf);
int rnd_pos(uchar * buf, uchar *pos);
int get_row(azio_stream *file_to_read, uchar *buf);
int get_row_version2(azio_stream *file_to_read, uchar *buf);
int get_row_version3(azio_stream *file_to_read, uchar *buf);
Archive_share *get_share(const char *table_name, int *rc);
int init_archive_reader();
// Always try auto_repair in case of HA_ERR_CRASHED_ON_USAGE
bool auto_repair(int error) const
{ return error == HA_ERR_CRASHED_ON_USAGE; }
int read_data_header(azio_stream *file_to_read);
void position(const uchar *record);
int info(uint);
int extra(enum ha_extra_function operation);
void update_create_info(HA_CREATE_INFO *create_info);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
int check_for_upgrade(HA_CHECK_OPT *check_opt);
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
enum row_type get_row_type() const
{
return ROW_TYPE_COMPRESSED;
}
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
bool is_crashed() const;
int check(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd);
uint32 max_row_length(const uchar *buf);
bool fix_rec_buff(unsigned int length);
int unpack_row(azio_stream *file_to_read, uchar *record);
unsigned int pack_row(const uchar *record, azio_stream *writer);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
int external_lock(THD *thd, int lock_type);
private:
void flush_and_clear_pending_writes();
};