NUL-terminate each individual number to be parsed.
To do this, the next command character and a pointer to its argument
are found and stored. The command character is then overwritten by NUL
before kstr* functions are called on the buffer.

Signed-off-by: Robert Abel <[email protected]>
---
 drivers/auxdisplay/charlcd.c | 53 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index a3d364e6c666..24cabe88c7f0 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -471,28 +471,63 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
                break;
        }
        case 'x':       /* gotoxy : LxXXX[yYYY]; */
-       case 'y':       /* gotoxy : LyYYY[xXXX]; */
+       case 'y': {     /* gotoxy : LyYYY[xXXX]; */
+
+               char* nxt_esc;
+               char  nxt_cmd;
+               char  cmd;
+               struct charlcd_priv_addr tmp_addr;
+
                if (!strchr(esc, ';'))
                        break;
 
-               while (*esc) {
-                       if (*esc == 'x') {
-                               esc++;
-                               if (kstrtoul(esc, 10, &priv->addr.x) < 0)
+               /* sequence is processed whether legal or illegal */
+               processed = 1;
+
+               /* copy current address to temporary buffer */
+               tmp_addr = priv->addr;
+
+               nxt_cmd = *esc++;
+               nxt_esc = esc;
+
+               while ('\0' != *esc) {
+
+                       cmd = nxt_cmd;
+                       esc = nxt_esc;
+                       nxt_esc = strpbrk(esc, "xy;");
+                       if (NULL != nxt_esc) {
+                               nxt_cmd = *nxt_esc;
+                               /* terminate current sequence with NUL */
+                               *nxt_esc++ = '\0';
+                       }
+
+                       if ('x' == cmd) {
+                               if (kstrtoul(esc, 10, &tmp_addr.x) < 0)
                                        break;
-                       } else if (*esc == 'y') {
-                               esc++;
-                               if (kstrtoul(esc, 10, &priv->addr.y) < 0)
+                       } else if ('y' == cmd) {
+                               if (kstrtoul(esc, 10, &tmp_addr.y) < 0)
                                        break;
                        } else {
+                               /* break on unknown command or ';' */
                                break;
                        }
+
                }
 
+               /* unknown commands in sequence will be followed by at least 
';' */
+               if ('\0' != *esc)
+                       break;
+
+               /* clamp new x/y coordinates */
+               if (tmp_addr.x >= lcd->width)
+                       tmp_addr.x = lcd->width - 1;
+               tmp_addr.y %= lcd->height;
+
+               priv->addr = tmp_addr;
                charlcd_gotoxy(lcd);
-               processed = 1;
                break;
        }
+       }
 
        /* TODO: This indent party here got ugly, clean it! */
        /* Check whether one flag was changed */
-- 
2.11.0

Reply via email to