From 3f7118f07725ca6c085b00aea3054d1d6814c0aa Mon Sep 17 00:00:00 2001 From: Martijn Smidt Date: Mon, 12 Jul 2021 16:27:05 +0200 Subject: [PATCH 1/2] Fixes mediumint unsigned overflowing inside uint32 #299 --- dml_events.go | 5 ++++- uint24.go | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 uint24.go diff --git a/dml_events.go b/dml_events.go index 9935da66..55653489 100644 --- a/dml_events.go +++ b/dml_events.go @@ -292,7 +292,7 @@ func NewBinlogDMLEvents(table *TableSchema, ev *replication.BinlogEvent, pos, re ) } for i, col := range table.Columns { - if col.IsUnsigned { + if col.IsUnsigned && col.Type != schema.TYPE_MEDIUM_INT { switch v := row[i].(type) { case int64: row[i] = uint64(v) @@ -305,6 +305,9 @@ func NewBinlogDMLEvents(table *TableSchema, ev *replication.BinlogEvent, pos, re case int: row[i] = uint(v) } + } else if col.IsUnsigned && col.Type == schema.TYPE_MEDIUM_INT { + val := row[i].(int32) + row[i] = NewUint24(val).Uint32() } } } diff --git a/uint24.go b/uint24.go new file mode 100644 index 00000000..fac9c15e --- /dev/null +++ b/uint24.go @@ -0,0 +1,27 @@ +// with the courtesy of this github file: https://github.com/Cryptkeeper/go-fseq/blob/v0.2.6/pkg/uint24/uint24.go +// used to convert a int32 to uint24 (mediumint) +package ghostferry + +const MaxUint24 = 1<<24 - 1 + +func NewUint24(val int32) *Uint24 { + var u = new(Uint24) + u.Set(val) + return u +} + +type Uint24 [3]uint8 + +func (u *Uint24) Set(val int32) { + // panic since this is closer to how a compiler/runtime would treat an overflow compared to err returns + if val > MaxUint24 { + panic("cannot set Uint24 larger than uint24.MaxUint24") + } + (*u)[0] = uint8(val & 0xFF) + (*u)[1] = uint8((val >> 8) & 0xFF) + (*u)[2] = uint8((val >> 16) & 0xFF) +} + +func (u Uint24) Uint32() uint32 { + return uint32(u[0]) | uint32(u[1])<<8 | uint32(u[2])<<16 +} \ No newline at end of file From b1d405a6fa79072bb3c587bfdccef4557909eb8b Mon Sep 17 00:00:00 2001 From: Martijn Smidt Date: Mon, 12 Jul 2021 17:15:55 +0200 Subject: [PATCH 2/2] also accept null/nil values --- dml_events.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dml_events.go b/dml_events.go index 55653489..f5a6172a 100644 --- a/dml_events.go +++ b/dml_events.go @@ -306,8 +306,10 @@ func NewBinlogDMLEvents(table *TableSchema, ev *replication.BinlogEvent, pos, re row[i] = uint(v) } } else if col.IsUnsigned && col.Type == schema.TYPE_MEDIUM_INT { - val := row[i].(int32) - row[i] = NewUint24(val).Uint32() + if row[i] != nil { + val := row[i].(int32) + row[i] = NewUint24(val).Uint32() + } } } }