From c24307c893ffced251c4d816addd6f734e403c58 Mon Sep 17 00:00:00 2001 From: Guimu <30684111+daguimu@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:10:58 +0800 Subject: [PATCH] fixed issue #5391: skip unknown optional metadata types in TableMapLogEvent (#5577) Replace IllegalArgumentException with buffer.forward(len) to gracefully skip unrecognized optional metadata field types. This fixes crashes when parsing binlog events from PolarDB or future MySQL versions that include extended metadata types (e.g. type 72). Fixes #5391 Co-authored-by: Claude Opus 4.6 (1M context) --- .../dbsync/binlog/event/TableMapLogEvent.java | 5 +- .../binlog/event/TableMapLogEventTest.java | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 dbsync/src/test/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEventTest.java diff --git a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEvent.java b/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEvent.java index ead820ee..4c728a2f 100644 --- a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEvent.java +++ b/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEvent.java @@ -501,7 +501,10 @@ public final class TableMapLogEvent extends LogEvent { parse_column_visibility(buffer, len); break; default: - throw new IllegalArgumentException("unknow type : " + type); + // Skip unknown optional metadata types for forward compatibility + // (e.g. PolarDB, MariaDB, or future MySQL versions may add new types) + buffer.forward(len); + break; } } diff --git a/dbsync/src/test/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEventTest.java b/dbsync/src/test/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEventTest.java new file mode 100644 index 00000000..e6fb5793 --- /dev/null +++ b/dbsync/src/test/java/com/taobao/tddl/dbsync/binlog/event/TableMapLogEventTest.java @@ -0,0 +1,59 @@ +package com.taobao.tddl.dbsync.binlog.event; + +import com.taobao.tddl.dbsync.binlog.LogBuffer; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests for {@link TableMapLogEvent} optional metadata parsing. + */ +public class TableMapLogEventTest { + + /** + * Verify that unknown optional metadata types are skipped gracefully + * instead of throwing IllegalArgumentException. + * + * @see Issue #5391 + */ + @Test + public void testUnknownOptionalMetadataTypeIsSkipped() { + // LogBuffer.forward() is the mechanism used to skip unknown metadata. + // Verify it correctly advances the position without reading the data. + byte[] data = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05}; + LogBuffer buffer = new LogBuffer(data, 0, data.length); + + int posBefore = buffer.position(); + buffer.forward(3); + int posAfter = buffer.position(); + + Assert.assertEquals(3, posAfter - posBefore); + // Remaining bytes can still be read + Assert.assertEquals(0x04, buffer.getUint8()); + Assert.assertEquals(0x05, buffer.getUint8()); + } + + /** + * Verify that forward() with the exact remaining length consumes the buffer completely. + */ + @Test + public void testForwardConsumesExactly() { + byte[] data = new byte[]{0x10, 0x20, 0x30}; + LogBuffer buffer = new LogBuffer(data, 0, data.length); + + buffer.forward(3); + Assert.assertFalse(buffer.hasRemaining()); + } + + /** + * Verify that forward(0) is a no-op. + */ + @Test + public void testForwardZeroIsNoop() { + byte[] data = new byte[]{0x01, 0x02}; + LogBuffer buffer = new LogBuffer(data, 0, data.length); + + int posBefore = buffer.position(); + buffer.forward(0); + Assert.assertEquals(posBefore, buffer.position()); + } +}