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

jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a7f1b5005a drivers/syslog: fix syslog_write() returning -EIO on every 
write
5a7f1b5005a is described below

commit 5a7f1b5005acdd810cadc20340684dfa6b8670d1
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Jul 28 13:53:11 2026 +0200

    drivers/syslog: fix syslog_write() returning -EIO on every write
    
    syslog_write_foreach() compares an unsigned count against a signed
    accumulator:
    
      size_t  nwritten     = 0;
      ssize_t nwritten_max = -EIO;
      ...
      if (nwritten > nwritten_max)
        {
          nwritten_max = nwritten;
        }
      return nwritten_max;
    
    The usual arithmetic conversions promote nwritten_max to size_t, so -EIO
    becomes 4294967291 on a 32-bit target, and the comparison is never true.
    nwritten_max keeps its initial value and the function returns -EIO no
    matter how many bytes actually went out.  Observed under gdb on a running
    target: nwritten == 64, nwritten_max == -5, (nwritten > nwritten_max) == 0.
    
    Most callers discard the result -- syslog() itself returns void -- so this
    is normally invisible.  It becomes fatal when /dev/console is backed by
    syslog_console_write(), because then stdio acts on it.
    lib_fflush_unlocked() sees a negative return, sets __FS_FLAG_ERROR and
    returns early, before resetting fs_bufpos.  The bytes have already been
    emitted, but the buffer is never cleared, so every subsequent stdio call
    re-flushes the same CONFIG_STDIO_BUFFER_SIZE bytes.  The console fills
    with one repeated fragment and the system makes no further progress.
    
    Reaching that state needs CONFIG_CONSOLE_SYSLOG=y together with no driver
    claiming /dev/console ahead of syslog_console_init().  Three in-tree
    defconfigs qualify: x86/qemu-i486:ostest, renesas/skp16c26:ostest and
    x86_64/qemu-intel64:earlyfb.  The other 56 CONSOLE_SYSLOG configurations
    have a serial console that registers /dev/console first, which is why this
    has gone unnoticed.
    
    Introduced by 1685e8ff7b ("syslog: avoid an infinite loop if one channel
    fails"), which changed nwritten_max from size_t to ssize_t = -EIO so that
    an all-channels-failed case could be reported.  Give nwritten the same type
    so the comparison is signed, which preserves that intent: nwritten_max
    stays -EIO only when no channel wrote anything.  nwritten is never negative,
    so the remaining comparisons against buflen are unaffected.
    
    Signed-off-by: Marco Casaroli <[email protected]>
    
    Assisted-by: Claude Opus 5 (1M context) <[email protected]>
---
 drivers/syslog/syslog_write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/syslog/syslog_write.c b/drivers/syslog/syslog_write.c
index 94e6c0d330e..51ac92d6363 100644
--- a/drivers/syslog/syslog_write.c
+++ b/drivers/syslog/syslog_write.c
@@ -106,7 +106,7 @@ ssize_t syslog_write_foreach(FAR const char *buffer,
 {
   syslog_write_t write;
   syslog_putc_t  putc;
-  size_t nwritten = 0;
+  ssize_t nwritten = 0;
   ssize_t nwritten_max = -EIO;
   ssize_t ret;
   int i;

Reply via email to