Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2f410c0 authored by Pengquan Meng's avatar Pengquan Meng
Browse files

Fixed invalid pdu issue

The device may receive invalid sms pdu, i.e the pdu contins sms header
with an invalid seqNumber. This caused InboundSmsHandler crashed constantly.
This CL added the range check for the seqNumber to ensure the
InboundSmsHandler will not crash even if the seqNumber is invalid.

Test: runtest -x GsmInboundSmsHandlerTest -m
testMultiPartSmsWithInvalidSeqNumber
Bug: 72298611

Merged-In: Icf291c8530abdc2a528c5cf227cf00135281b899
Change-Id: Icf291c8530abdc2a528c5cf227cf00135281b899
(cherry picked from commit 9eec9d02)
parent 78943009
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -759,6 +759,13 @@ public abstract class InboundSmsHandler extends StateMachine {
        int destPort = tracker.getDestPort();
        boolean block = false;

        // Do not process when the message count is invalid.
        if (messageCount <= 0) {
            loge("processMessagePart: returning false due to invalid message count "
                    + messageCount);
            return false;
        }

        if (messageCount == 1) {
            // single-part message
            pdus = new byte[][]{tracker.getPdu()};
@@ -794,6 +801,17 @@ public abstract class InboundSmsHandler extends StateMachine {
                    int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                            .get(SEQUENCE_COLUMN)) - tracker.getIndexOffset();

                    // The invalid PDUs can be received and stored in the raw table. The range
                    // check ensures the process not crash even if the seqNumber in the
                    // UserDataHeader is invalid.
                    if (index >= pdus.length || index < 0) {
                        loge(String.format(
                                "processMessagePart: invalid seqNumber = %d, messageCount = %d",
                                index + tracker.getIndexOffset(),
                                messageCount));
                        continue;
                    }

                    pdus[index] = HexDump.hexStringToByteArray(cursor.getString(
                            PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)));

+44 −0
Original line number Diff line number Diff line
@@ -604,6 +604,50 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
        assertEquals("IdleState", getCurrentState().getName());
    }

    @Test
    @MediumTest
    public void testMultiPartSmsWithInvalidSeqNumber() {
        transitionFromStartupToIdle();

        // prepare SMS part 1 and part 2
        prepareMultiPartSms(false);

        mSmsHeader.concatRef = new SmsHeader.ConcatRef();
        doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader();

        doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
                .makeInboundSmsTracker(nullable(byte[].class), anyLong(), anyInt(), anyBoolean(),
                        nullable(String.class), nullable(String.class), anyInt(), anyInt(),
                        anyInt(), anyBoolean(), nullable(String.class));
        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
                mSmsMessage, null));
        waitForMs(100);

        // verify the message is stored in the raw table
        assertEquals(1, mContentProvider.getNumRows());

        // State machine should go back to idle and wait for second part
        assertEquals("IdleState", getCurrentState().getName());

        // change seqNumber in part 2 to an invalid value
        int invalidSeqNumber = -1;
        mInboundSmsTrackerCVPart2.put("sequence", invalidSeqNumber);
        doReturn(invalidSeqNumber).when(mInboundSmsTrackerPart2).getSequenceNumber();

        doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
                .makeInboundSmsTracker(nullable(byte[].class), anyLong(), anyInt(), anyBoolean(),
                        nullable(String.class), nullable(String.class), anyInt(), anyInt(),
                        anyInt(), anyBoolean(), nullable(String.class));
        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
                mSmsMessage, null));
        waitForMs(100);

        // verify no broadcasts sent
        verify(mContext, never()).sendBroadcast(any(Intent.class));
        // State machine should go back to idle
        assertEquals("IdleState", getCurrentState().getName());
    }

    @Test
    @MediumTest
    public void testMultipartSmsFromBlockedNumber_noBroadcastsSent() {