| Bug #42803 | Field_bit does not have unsigned_flag field, can lead to bad memory access | ||
|---|---|---|---|
| Submitted: | 12 Feb 2009 19:11 | Modified: | 18 Dec 2009 13:21 |
| Reporter: | Gene Pang | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
| Version: | 5.0.37, 4.1, 5.0, 5.1, 6.0 bzr | OS: | Any |
| Assigned to: | Ramil Kalimullin | CPU Architecture: | Any |
| Tags: | Contribution, Field_bit, unsigned_flag | ||
[14 Feb 2009 12:41]
Sveta Smirnova
Thank you for the report. Memory leak verified with following valgrind output (version 6.0): CURRENT_TEST: main.bug42803 ==7364== Memcheck, a memory error detector. ==7364== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al. ==7364== Using LibVEX rev 1854, a library for dynamic binary translation. ==7364== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP. ==7364== Using valgrind-3.3.1, a dynamic binary instrumentation framework. ==7364== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al. ==7364== For more details, rerun with: -v ==7364== 090214 15:35:04 [Warning] The syntax '--log' is deprecated and will be removed in MySQL 7.0. Please use '--general-log --general-log-file' instead. 090214 15:35:05 [Warning] The syntax '--log-slow-queries' is deprecated and will be removed in MySQL 7.0. Please use '--slow-query-log'/'--slow-query-log-file' instead. 090214 15:35:05 [Note] Plugin 'InnoDB' disabled by command line option 090214 15:35:07 [Note] Falcon: unable to open system data files. 090214 15:35:07 [Note] Falcon: creating new system data files. 090214 15:35:13 [Note] Event Scheduler: Loaded 0 events 090214 15:35:13 [Note] /users/ssmirnova/build/mysql-6.0/libexec/mysqld: ready for connections. Version: '6.0.10-alpha-debug-log' socket: '/users/ssmirnova/build/mysql-6.0/mysql-test/var/tmp/mysqld.1.sock' port: 12500 Source distribution ==7364== Thread 15: ==7364== Syscall param write(buf) points to uninitialised byte(s) ==7364== at 0x46419B: (within /lib/libpthread-2.3.6.so) ==7364== by 0x87ECDEE: my_b_flush_io_cache (mf_iocache.c:1771) ==7364== by 0x87ED199: end_io_cache (mf_iocache.c:1859) ==7364== by 0x84F979D: mi_extra (mi_extra.c:171) ==7364== by 0x84EADC9: ha_myisam::end_bulk_insert(bool) (ha_myisam.cc:1399) ==7364== by 0x8376A5C: handler::ha_end_bulk_insert(bool) (handler.h:1609) ==7364== by 0x83715F0: mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool) (sql_insert.cc:866) ==7364== by 0x82D20C1: mysql_execute_command(THD*) (sql_parse.cc:3122) ==7364== by 0x82D80B4: mysql_parse(THD*, char const*, unsigned, char const**) (sql_parse.cc:5751) ==7364== by 0x82D8AF6: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1009) ==7364== by 0x82D9E5A: do_command(THD*) (sql_parse.cc:691) ==7364== by 0x82C7D6A: handle_one_connection (sql_connect.cc:1146) ==7364== by 0x45FBD3: start_thread (in /lib/libpthread-2.3.6.so) ==7364== by 0x3B74FD: clone (in /lib/libc-2.3.6.so) ==7364== Address 0x7fab5a9 is 25 bytes inside a block of size 131,100 alloc'd ==7364== at 0x40047ED: malloc (vg_replace_malloc.c:207) ==7364== by 0x87EFE29: _mymalloc (safemalloc.c:137) ==7364== by 0x87E9F16: init_io_cache (mf_iocache.c:238) ==7364== by 0x84F96F0: mi_extra (mi_extra.c:139) ==7364== by 0x84EAC04: ha_myisam::start_bulk_insert(unsigned long long) (ha_myisam.cc:1357) ==7364== by 0x8376A20: handler::ha_start_bulk_insert(unsigned long long) (handler.h:1604) ==7364== by 0x83711B4: mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool) (sql_insert.cc:751) ==7364== by 0x82D20C1: mysql_execute_command(THD*) (sql_parse.cc:3122) ==7364== by 0x82D80B4: mysql_parse(THD*, char const*, unsigned, char const**) (sql_parse.cc:5751) ==7364== by 0x82D8AF6: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1009) ==7364== by 0x82D9E5A: do_command(THD*) (sql_parse.cc:691) ==7364== by 0x82C7D6A: handle_one_connection (sql_connect.cc:1146) ==7364== by 0x45FBD3: start_thread (in /lib/libpthread-2.3.6.so) ==7364== by 0x3B74FD: clone (in /lib/libc-2.3.6.so) ==7364== ==7364== Syscall param pwrite64(buf) points to uninitialised byte(s) ==7364== at 0x464EA7: pwrite64 (in /lib/libpthread-2.3.6.so) ==7364== by 0x87E146C: my_pwrite (my_pread.c:162) ==7364== by 0x87E2CEC: key_cache_pwrite (mf_keycache.c:796) ==7364== by 0x87E8473: flush_cached_blocks (mf_keycache.c:3540) ==7364== by 0x87E8B23: flush_key_blocks_int (mf_keycache.c:3836) ==7364== by 0x87E9069: flush_key_blocks (mf_keycache.c:4093) ==7364== by 0x85037F0: mi_lock_database (mi_locking.c:72) ==7364== by 0x84EBF33: ha_myisam::external_lock(THD*, int) (ha_myisam.cc:1752) ==7364== by 0x8407297: handler::ha_external_lock(THD*, int) (handler.cc:5400) ==7364== by 0x82B2DA0: unlock_external(THD*, TABLE**, unsigned) (lock.cc:823) ==7364== by 0x82B2E57: mysql_unlock_tables(THD*, st_mysql_lock*) (lock.cc:438) ==7364== by 0x831AA12: close_thread_tables(THD*, bool) (sql_base.cc:1459) ==7364== by 0x82D99F7: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1410) ==7364== by 0x82D9E5A: do_command(THD*) (sql_parse.cc:691) ==7364== by 0x82C7D6A: handle_one_connection (sql_connect.cc:1146) ==7364== by 0x45FBD3: start_thread (in /lib/libpthread-2.3.6.so) ==7364== Address 0x412b9ac is 3,516 bytes inside a block of size 923,676 alloc'd ==7364== at 0x40047ED: malloc (vg_replace_malloc.c:207) ==7364== by 0x87EFE29: _mymalloc (safemalloc.c:137) ==7364== by 0x880DF8A: my_large_malloc (my_largepage.c:64) ==7364== by 0x87E22DB: init_key_cache (mf_keycache.c:438) ==7364== by 0x840611C: ha_init_key_cache (handler.cc:3640) ==7364== by 0x82E1FB0: process_key_caches(int (*)(char const*, st_key_cache*)) (set_var.cc:4499) ==7364== by 0x82BE78C: init_server_components() (mysqld.cc:4126) ==7364== by 0x82C2940: main (mysqld.cc:4643)
[8 Oct 2009 11:57]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/86142 2815 Ramil Kalimullin 2009-10-08 Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access Problem: Field_bit is the only field which returns INT_RESULT and doesn't have unsigned flag. As it's not a descendant of the Field_num, so using ((Field_num *) field_bit)->unsigned_flag may lead to unpredictable results. Fix: check the field type before casting. @ mysql-test/r/type_bit.result Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - test result. @ mysql-test/t/type_bit.test Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - test case. @ sql/opt_range.cc Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - don't cast to (Field_num *) Field_bit, as it's not a Field_num descendant and is always unsigned by nature.
[8 Oct 2009 16:54]
Ramil Kalimullin
Pushed to {5.0, 5.1}-bugteam, -pe.
[14 Oct 2009 14:35]
Bugs System
Pushed into 5.0.88 (revid:joro@sun.com-20091014143320-kwcqatf2g9cjbx43) (version source revid:ramil@mysql.com-20091008115631-jjozkd7q3g82x3iw) (merge vers: 5.0.87) (pib:13)
[14 Oct 2009 14:39]
Bugs System
Pushed into 5.1.41 (revid:joro@sun.com-20091014143611-cphb0enjlx6lpat1) (version source revid:satya.bn@sun.com-20091013071829-zc4c3go44j6re592) (merge vers: 5.1.40) (pib:13)
[15 Oct 2009 23:47]
Paul DuBois
Noted in 5.0.88, 5.1.41 changelogs. Failure to treat BIT values as unsigned could lead to unpredictable results. Setting report to NDI pending push into 5.5.x.+
[22 Oct 2009 6:36]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20091022063126-l0qzirh9xyhp0bpc) (version source revid:alik@sun.com-20091019135554-s1pvptt6i750lfhv) (merge vers: 6.0.14-alpha) (pib:13)
[22 Oct 2009 7:08]
Bugs System
Pushed into 5.5.0-beta (revid:alik@sun.com-20091022060553-znkmxm0g0gm6ckvw) (version source revid:alik@sun.com-20091019131708-bc6pv55x6287a0wc) (merge vers: 5.5.0-beta) (pib:13)
[22 Oct 2009 19:57]
Paul DuBois
Noted in 5.5.0, 6.0.14 changelogs.
[18 Dec 2009 10:35]
Bugs System
Pushed into 5.1.41-ndb-7.1.0 (revid:jonas@mysql.com-20091218102229-64tk47xonu3dv6r6) (version source revid:jonas@mysql.com-20091218095730-26gwjidfsdw45dto) (merge vers: 5.1.41-ndb-7.1.0) (pib:15)
[18 Dec 2009 10:51]
Bugs System
Pushed into 5.1.41-ndb-6.2.19 (revid:jonas@mysql.com-20091218100224-vtzr0fahhsuhjsmt) (version source revid:jonas@mysql.com-20091217101452-qwzyaig50w74xmye) (merge vers: 5.1.41-ndb-6.2.19) (pib:15)
[18 Dec 2009 11:06]
Bugs System
Pushed into 5.1.41-ndb-6.3.31 (revid:jonas@mysql.com-20091218100616-75d9tek96o6ob6k0) (version source revid:jonas@mysql.com-20091217154335-290no45qdins5bwo) (merge vers: 5.1.41-ndb-6.3.31) (pib:15)
[18 Dec 2009 11:20]
Bugs System
Pushed into 5.1.41-ndb-7.0.11 (revid:jonas@mysql.com-20091218101303-ga32mrnr15jsa606) (version source revid:jonas@mysql.com-20091218064304-ezreonykd9f4kelk) (merge vers: 5.1.41-ndb-7.0.11) (pib:15)
[18 Dec 2009 13:21]
MC Brown
Already noted in earlier changelogs.

Description: There is a possible incorrect memory access in opt_range.cc, get_mm_leaf(). In this code fragment, ((Field_num*)field)->unsigned_flag may not always work, since field could be Field_bit, and Field_bit does NOT have the unsigned_flag field. Field_bit is the only class where result_type() is INT_RESULT, but does NOT have unsigned_flag, from Field_num. /* Check if we are comparing an UNSIGNED integer with a negative constant. In this case we know that: (a) (unsigned_int [< | <=] negative_constant) == FALSE (b) (unsigned_int [> | >=] negative_constant) == TRUE In case (a) the condition is false for all values, and in case (b) it is true for all values, so we can avoid unnecessary retrieval and condition testing, and we also get correct comparison of unsinged integers with negative integers (which otherwise fails because at query execution time negative integers are cast to unsigned if compared with unsigned). */ if (field->result_type() == INT_RESULT && value->result_type() == INT_RESULT && ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag) { ... } How to repeat: I ran type_bit test with --valgrind. A smaller test case: create table t1 (a bit(7), b bit(9), key(a, b)); insert into t1 values (94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177), (75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380), (111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36), (116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499), (30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403), (44, 307), (68, 454), (57, 135); explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; Suggested fix: Checking for (field->type() == FIELD_TYPE_BIT) before casting it to Field_num would solve it, since Field_bit is always unsigned. if (field->result_type() == INT_RESULT && value->result_type() == INT_RESULT && ((field->type() == FIELD_TYPE_BIT) || ((Field_num*)field)->unsigned_flag) && !((Item_int*)value)->unsigned_flag) { ... }