From 2aeec7c371e16efaa86c5b159120b6aed7c466fc Mon Sep 17 00:00:00 2001 From: "hujiaming.0927" Date: Tue, 29 Nov 2022 01:25:46 +0800 Subject: [PATCH] [encoding/gsm7] Fix the bug of confusion with '@' when the first 7 bits of the last byte after GSM7(Packed) pack are all 0 Change-Id: I87dca3d5b1b21c1d722e630b8cb5228c57d5084e --- go.sum | 1 + smpp/encoding/gsm7.go | 14 ++++++++++++++ smpp/encoding/gsm7_test.go | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index 1fb1745..ab4f02a 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/fiorix/go-smpp v0.0.0-20210403173735-2894b96e70ba h1:vBqABUa2HUSc6tj22Tw+ZMVGHuBzKtljM38kbRanmrM= github.com/fiorix/go-smpp v0.0.0-20210403173735-2894b96e70ba/go.mod h1:VfKFK7fGeCP81xEhbrOqUEh45n73Yy6jaPWwTVbxprI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/smpp/encoding/gsm7.go b/smpp/encoding/gsm7.go index 9fbd997..31fa0a6 100644 --- a/smpp/encoding/gsm7.go +++ b/smpp/encoding/gsm7.go @@ -209,6 +209,10 @@ func (g *gsm7Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, er } } + if g.packed && len(septets)%8 == 0 && septets[len(septets)-1] == 0x0d { + septets = septets[:len(septets)-1] + } + nSeptet := 0 builder := bytes.NewBufferString("") for nSeptet < len(septets) { @@ -271,6 +275,7 @@ func (g *gsm7Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, er } nDst = len(septets) + unpackedLen := nDst if g.packed { nDst = int(math.Ceil(float64(len(septets)) * 7 / 8)) } @@ -354,5 +359,14 @@ func (g *gsm7Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, er } remain = len(septets) - nSeptet } + + // When there are 7 spare bits in the last octet of a message, these bits are set to the 7-bit code of the CR control + // (also used as a padding filler) instead of being set to zero (where they would be confused with the 7-bit code of an '@' character). + if g.packed && (unpackedLen*7)%8 == 1 { + if v := dst[nDst-1]; v == 0x01 || v == 0x00 { + dst[nDst-1] = v | 0x0d<<1 + } + } + return nDst, nSrc, err } diff --git a/smpp/encoding/gsm7_test.go b/smpp/encoding/gsm7_test.go index 8fd91e4..66b8c8d 100644 --- a/smpp/encoding/gsm7_test.go +++ b/smpp/encoding/gsm7_test.go @@ -41,7 +41,7 @@ var packedTests = []struct { {Text: "1234", Buff: []byte{0x31, 0xD9, 0x8C, 0x06}}, {Text: "12345", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0x03}}, {Text: "123456", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0x01}}, - {Text: "1234567", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x00}}, + {Text: "1234567", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x1A}}, {Text: "12345678", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x70}}, {Text: "123456789", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x70, 0x39}}, {Text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur nec nunc venenatis, ultricies ipsum id, volutpat ante. Sed pretium ac metus a interdum metus.", Buff: []byte("\xCC\xB7\xBC\xDC\x06\xA5\xE1\xF3\x7A\x1B\x44\x7E\xB3\xDF\x72\xD0\x3C\x4D\x07\x85\xDB\x65\x3A\x0B\x34\x7E\xBB\xE7\xE5\x31\xBD\x4C\xAF\xCB\x41\x61\x72\x1A\x9E\x9E\x8F\xD3\xEE\x33\xA8\xCC\x4E\xD3\x5D\xA0\x61\x5D\x1E\x16\xA7\xE9\x75\x39\xC8\x5D\x1E\x83\xDC\x75\xF7\x18\x64\x2F\xBB\xCB\xEE\x30\x3D\x3D\x67\x81\xEA\x6C\xBA\x3C\x3D\x4E\x97\xE7\xA0\x34\x7C\x5E\x6F\x83\xD2\x64\x16\xC8\xFE\x66\xD7\xE9\xF0\x30\x1D\x14\x76\xD3\xCB\x2E\xD0\xB4\x4C\x06\xC1\xE5\x65\x7A\xBA\xDE\x06\x85\xC7\xA0\x76\x99\x5E\x9F\x83\xC2\xA0\xB4\x9B\x5E\x96\x93\xEB\x6D\x50\xBB\x4C\xAF\xCF\x5D")}, @@ -204,3 +204,34 @@ func TestInvalidByte(t *testing.T) { } } } + +func TestExtraCR(t *testing.T) { + for _, item := range []struct { + name string + content string + }{ + {name: "would have CR", content: "1234567890abcdefghijklm"}, + {name: "would have CR, last byte is \\r", content: "1234567890abcdefghijkl\r"}, + {name: "would not have CR, but last byte is 1", content: "123456"}, + {name: "woud have CR, also has escape", content: "12345678[abcdefghijklmn"}, + {name: "would not have CR, not have escape", content: "012345678[abcdefghijklmno"}, + } { + encoder := GSM7(true).NewEncoder() + es, _, err := transform.Bytes(encoder, []byte(item.content)) + if err != nil { + t.Fatal(err) + } + + // t.Log(es, len(es)) + + decoder := GSM7(true).NewDecoder() + res, _, err := transform.Bytes(decoder, es) + if err != nil { + t.Fatal(err) + } + + if string(res) != item.content { + t.Fatalf("== %s not equal. %s vs %s", item.name, item.content, string(res)) + } + } +}