Skip to content

Commit

Permalink
Fixes mediumint unsigned overflowing inside uint32
Browse files Browse the repository at this point in the history
  • Loading branch information
HemeraOne committed Jul 12, 2021
1 parent 94203eb commit b4b6691
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
5 changes: 4 additions & 1 deletion dml_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions uint24.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit b4b6691

Please sign in to comment.