From 23fe39a7b7132dcb31fcdbd1fc92ae61398c7aec Mon Sep 17 00:00:00 2001 From: Buhle79 Date: Tue, 9 Jul 2024 14:16:06 +0200 Subject: [PATCH 1/3] fix crash loop for short message decode --- src/vumi2/transports/smpp/processors.py | 4 +-- tests/transports/smpp/test_processors.py | 40 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/vumi2/transports/smpp/processors.py b/src/vumi2/transports/smpp/processors.py index 5284fde..61231bc 100644 --- a/src/vumi2/transports/smpp/processors.py +++ b/src/vumi2/transports/smpp/processors.py @@ -360,7 +360,7 @@ async def _handle_deliver_sm_esm_class( if esm_class.type == EsmClassType.DEFAULT: return False, None - content = pdu.params["short_message"].decode() + content = pdu.params["short_message"].decode("latin1") match = self.regex.match(content) if not match: logger.warning( @@ -383,7 +383,7 @@ async def _handle_deliver_sm_body( Try to decode the body as a delivery report, even if the esm_class doesn't say it's a delivery report """ - content = pdu.params["short_message"].decode() + content = pdu.params["short_message"].decode("latin1") match = self.regex.match(content) if not match: return False, None diff --git a/tests/transports/smpp/test_processors.py b/tests/transports/smpp/test_processors.py index 8cf95f8..dbf0772 100644 --- a/tests/transports/smpp/test_processors.py +++ b/tests/transports/smpp/test_processors.py @@ -577,3 +577,43 @@ async def test_short_message_multipart(sm_processer: ShortMessageProcessor): assert msg.content == "part1part2" assert msg.from_addr == "27820001001" assert msg.to_addr == "123456" + + +async def test_invalid_delivery_report_esm_class_bad_encoding( + dr_processer: DeliveryReportProcesser, caplog +): + """ + If the ESM class says this is a delivery report, and it isn't UTF8-compatible, + then log a warning and don't return any event + """ + handled, event = await dr_processer.handle_deliver_sm( + DeliverSM( + esm_class=EsmClass( + EsmClassMode.DEFAULT, EsmClassType.SMSC_DELIVERY_RECEIPT + ), + short_message=b"\xa4\xe8 bad bytes", + ) + ) + assert handled is False + assert event is None + [log] = [log for log in caplog.records if log.levelno >= logging.WARNING] + + assert ( + log.getMessage() + == "esm_class SMSC_DELIVERY_RECEIPT indicates delivery report, but regex" + " does not match content: ยครจ bad bytes" + ) + + +async def test_delivery_report_body_bad_encoding(dr_processer: DeliveryReportProcesser): + """ + If it is not valid UTF-8, don't throw a UnicodeDecodeError + """ + handled, event = await dr_processer.handle_deliver_sm( + DeliverSM( + esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT), + short_message=b"\xa4\xe8 bad bytes", + ) + ) + assert handled is False + assert event is None From 7f91ad0436b894eebfa2251ef6c0c5f93cc34c3d Mon Sep 17 00:00:00 2001 From: buhle79 Date: Tue, 9 Jul 2024 15:26:59 +0200 Subject: [PATCH 2/3] Adding comment for using latin1 on decode --- src/vumi2/transports/smpp/processors.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vumi2/transports/smpp/processors.py b/src/vumi2/transports/smpp/processors.py index 61231bc..2a7bbf2 100644 --- a/src/vumi2/transports/smpp/processors.py +++ b/src/vumi2/transports/smpp/processors.py @@ -360,6 +360,11 @@ async def _handle_deliver_sm_esm_class( if esm_class.type == EsmClassType.DEFAULT: return False, None + """ + The SMPP spec doesn't mention encodings at all for + delivery reports, so assume they're plain ASCII and decode + with latin1 to avoid decode errors. + """ content = pdu.params["short_message"].decode("latin1") match = self.regex.match(content) if not match: From 0cadafdb05c9795c05c9b0ad881ce3f398aa778d Mon Sep 17 00:00:00 2001 From: buhle79 Date: Tue, 9 Jul 2024 15:42:18 +0200 Subject: [PATCH 3/3] Fix format --- src/vumi2/transports/smpp/processors.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vumi2/transports/smpp/processors.py b/src/vumi2/transports/smpp/processors.py index 2a7bbf2..706a9e0 100644 --- a/src/vumi2/transports/smpp/processors.py +++ b/src/vumi2/transports/smpp/processors.py @@ -360,11 +360,10 @@ async def _handle_deliver_sm_esm_class( if esm_class.type == EsmClassType.DEFAULT: return False, None - """ - The SMPP spec doesn't mention encodings at all for - delivery reports, so assume they're plain ASCII and decode - with latin1 to avoid decode errors. - """ + # The SMPP spec doesn't mention encodings at all for + # delivery reports, so assume they're plain ASCII and decode + # with latin1 to avoid decode errors. + content = pdu.params["short_message"].decode("latin1") match = self.regex.match(content) if not match: