This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch releases/12.13
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/releases/12.13 by this push:
     new ab0ad3cee51 drivers/net/telnet: Ignore unsupported subnegotiation data.
ab0ad3cee51 is described below

commit ab0ad3cee517bbc8c92159cd56b96dbe3c13f5a6
Author: Shunchao Hu <[email protected]>
AuthorDate: Tue Mar 24 15:52:11 2026 +0800

    drivers/net/telnet: Ignore unsupported subnegotiation data.
    
    Ignore unsupported telnet subnegotiation payload until `IAC SE` so
    option bytes do not leak into the first NSH command.
    
    Keep existing NAWS handling intact and also treat `IAC IAC` inside
    subnegotiation payload as an escaped `0xFF` data byte rather than a
    subnegotiation terminator.
    
    This makes subnegotiation parsing RFC-compliant for both unsupported
    options and NAWS payload processing.
    
    Signed-off-by: Shunchao Hu <[email protected]>
---
 drivers/net/telnet.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/drivers/net/telnet.c b/drivers/net/telnet.c
index 08c23e0dbbf..6cd92ebf8b2 100644
--- a/drivers/net/telnet.c
+++ b/drivers/net/telnet.c
@@ -107,8 +107,8 @@ enum telnet_state_e
   STATE_DO,
   STATE_DONT,
   STATE_SB,
-  STATE_SB_NAWS,
-  STATE_SE
+  STATE_SB_DATA,
+  STATE_SB_NAWS
 };
 
 /* This structure describes the internal state of the driver */
@@ -118,6 +118,7 @@ struct telnet_dev_s
   uint8_t           td_state;     /* (See telnet_state_e) */
   uint8_t           td_crefs;     /* The number of open references to the 
session */
   uint8_t           td_minor;     /* Minor device number */
+  bool              td_sb_iac;    /* Saw IAC within sub-negotiation payload */
   uint16_t          td_offset;    /* Offset to the valid, pending bytes in the 
rxbuffer */
   uint16_t          td_pending;   /* Number of valid, pending bytes in the 
rxbuffer */
 #ifdef CONFIG_TELNET_SUPPORT_NAWS
@@ -372,16 +373,17 @@ static ssize_t telnet_receive(FAR struct telnet_dev_s 
*priv,
                       priv->td_state = STATE_DONT;
                       break;
 
-#ifdef CONFIG_TELNET_SUPPORT_NAWS
                     case TELNET_SB:
                       priv->td_state = STATE_SB;
+                      priv->td_sb_iac = false;
+#ifdef CONFIG_TELNET_SUPPORT_NAWS
                       priv->td_sb_count = 0;
+#endif
                       break;
 
                     case TELNET_SE:
                       priv->td_state = STATE_NORMAL;
                       break;
-#endif
 
                     default:
                       priv->td_state = STATE_NORMAL;
@@ -458,25 +460,58 @@ static ssize_t telnet_receive(FAR struct telnet_dev_s 
*priv,
               }
             break;
 
-#ifdef CONFIG_TELNET_SUPPORT_NAWS
-          /* Handle Telnet Sub negotiation request */
+          /* Handle Telnet sub-negotiation requests. */
 
           case STATE_SB:
             switch (ch)
               {
+#ifdef CONFIG_TELNET_SUPPORT_NAWS
                 case TELNET_NAWS:
                   priv->td_state = STATE_SB_NAWS;
                   break;
+#endif
 
                 default:
-                  priv->td_state = STATE_NORMAL;
+                  priv->td_state = STATE_SB_DATA;
                   break;
               }
             break;
 
+          /* Ignore unsupported sub-negotiation payload until IAC SE. */
+
+          case STATE_SB_DATA:
+            if (priv->td_sb_iac)
+              {
+                priv->td_sb_iac = false;
+                if (ch == TELNET_SE)
+                  {
+                    priv->td_state = STATE_NORMAL;
+                  }
+              }
+            else if (ch == TELNET_IAC)
+              {
+                priv->td_sb_iac = true;
+              }
+            break;
+
+#ifdef CONFIG_TELNET_SUPPORT_NAWS
           /* Handle NAWS sub-option negotiation */
 
           case STATE_SB_NAWS:
+            if (priv->td_sb_iac)
+              {
+                priv->td_sb_iac = false;
+                if (ch == TELNET_SE)
+                  {
+                    priv->td_state = STATE_NORMAL;
+                    break;
+                  }
+              }
+            else if (ch == TELNET_IAC)
+              {
+                priv->td_sb_iac = true;
+                break;
+              }
 
             /* Update cols / rows based on received byte count */
 
@@ -500,11 +535,11 @@ static ssize_t telnet_receive(FAR struct telnet_dev_s 
*priv,
                   break;
               }
 
-            /* Increment SB count and switch to NORMAL when complete */
+            /* Increment SB count and keep discarding until IAC SE. */
 
             if (++priv->td_sb_count == 4)
               {
-                priv->td_state = STATE_NORMAL;
+                priv->td_state = STATE_SB_DATA;
               }
 
             break;

Reply via email to