From nobody Sat May 4 19:10:07 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1591280005; cv=none; d=zohomail.com; s=zohoarc; b=K9B+Bded9By2EK4a+b3YknRHw7L44tNnrFb+wEaqqluaN4hElJKVER1VOB3NgDEPM7x75SI8c0LdoPElHKN1rN+RO+cBL7qdUlpTSJ3MZOOiWOxFln6tNogMbuZVKd+tDoUV7re++eXgzJZpUC0UjkmB+fQYLfFKv3kXIfWV5M0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1591280005; h=Content-Type:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=wVv2+W3o+vDQgsPtbwKEPRyvhSw7NBNSkdtKVT7cqCI=; b=dQIuJL754dCfEGCK/tGMWS4dOPt24Tbm5eavXxsfmlVUsNnOBPfOqbuf17n+hQAodODEQ0xeZ/gaxWG7XB/sz6oALcwNucx7y7vMUUkbjWoCicgVaQTRvlTk5/QS6LGDl6x5WEoVdWRnVvn2AzS267+5XTir8decEU0gEYz6PVE= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1591280005246650.4967377552897; Thu, 4 Jun 2020 07:13:25 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jgqc1-0006By-OK; Thu, 04 Jun 2020 14:12:53 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jgqc1-0006Bt-1l for xen-devel@lists.xenproject.org; Thu, 04 Jun 2020 14:12:53 +0000 Received: from esa2.hc3370-68.iphmx.com (unknown [216.71.145.153]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 799c51c0-a66d-11ea-8993-bc764e2007e4; Thu, 04 Jun 2020 14:12:51 +0000 (UTC) X-Inumbo-ID: 799c51c0-a66d-11ea-8993-bc764e2007e4 Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: r7lOM1xHIpM87SQ0kT3E1TYuTair+lwl4sJwUNQoAHk1W+k5+iTppNTfEMAPNN+EAw9DZgyUlw ZJD9zwmCSVS8KEVaWvhwIhuj/iEwwrndr79c5SNqaraplltwwCrWiA9GuXtSGMkT3kwRujXOia 2UtlxMW5TG2t6BGqkb/nfyvGydSFXLEsx05SzAv9qoDjYEAdbNufJk5/bKOYa518Gz5ImvYPHo CWr17MqI4pJDUojKIudlgrLH3OdE9ByeOwHX9u16IKUl7bigdaGf3Bm5f5pRY34S1F6+/cKRhY qCo= X-SBRS: 2.7 X-MesageID: 19251302 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.73,472,1583211600"; d="scan'208";a="19251302" From: Andrew Cooper To: Subject: [PATCH XTF] vsnprintf: Expand \n to \r\n for console output Date: Thu, 4 Jun 2020 15:12:23 +0100 Message-ID: <20200604141223.14153-1-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Pawel Wieczorkiewicz , Andrew Cooper Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" xenconsoled doesn't automatically convert \n into \r\n, which causes test output appear like this in a terminal: [root@host ~]# xl create -c tests/selftest/test-pv64-selftest.cfg Parsing config from tests/selftest/test-pv64-selftest.cfg --- Xen Test Framework --- Environment: PV 64bit (Long mode 4 levels) XTF S= elftests There are a number of ways to do this, but by far the most efficient way is= to have vsnprintf() expand \n's in the output buffer. This however is non-standard behaviour for vsnprintf(). Rename it to vsnprintf_internal() and take extra flags, and have vprintk() use the new LF_TO_CRLF control flag. Inside vsnprintf_internal(), rearrange the non-format and %c logic to share the expansion logic, as well as extending the logic to fmt_string(). Extend the selftests to confirm correct behaviour in both modes, for all wa= ys of being able to pass newline characters into a format operation. Reported-by: Pawel Wieczorkiewicz Signed-off-by: Andrew Cooper --- Pawel: Does this fix the issues you were seeing? --- common/console.c | 2 +- common/libc/vsnprintf.c | 23 +++++++++++++++-------- include/xtf/libc.h | 15 ++++++++++++++- tests/selftest/main.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/common/console.c b/common/console.c index 0724fc9f..b3e89473 100644 --- a/common/console.c +++ b/common/console.c @@ -122,7 +122,7 @@ void vprintk(const char *fmt, va_list args) unsigned int i; int rc; =20 - rc =3D vsnprintf(buf, sizeof(buf), fmt, args); + rc =3D vsnprintf_internal(buf, sizeof(buf), fmt, args, LF_TO_CRLF); =20 if ( rc > (int)sizeof(buf) ) panic("vprintk() buffer overflow\n"); diff --git a/common/libc/vsnprintf.c b/common/libc/vsnprintf.c index a49fd308..c907d42b 100644 --- a/common/libc/vsnprintf.c +++ b/common/libc/vsnprintf.c @@ -47,6 +47,7 @@ static int isdigit(int c) /* Conversions */ #define UPPER (1u << 5) #define SIGNED (1u << 6) +/* Careful not to overlap with vsnprintf_internal() flags. */ =20 /* Shorthand for ensuring str moves forwards, but not overruning the buffe= r. */ #define PUT(c) \ @@ -185,7 +186,11 @@ char *fmt_string(char *str, char *end, const char *val, PUT(' '); =20 for ( i =3D 0; i < len; ++i ) + { + if ( (flags & LF_TO_CRLF) && val[i] =3D=3D '\n' ) + PUT('\r'); PUT(val[i]); + } =20 while ( len < width-- ) PUT(' '); @@ -268,7 +273,8 @@ static char *pointer( width, precision, flags); } =20 -int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +int vsnprintf_internal(char *buf, size_t size, const char *fmt, va_list ar= gs, + unsigned int caller_flags) { char *str =3D buf, *end =3D buf + size; =20 @@ -277,15 +283,15 @@ int vsnprintf(char *buf, size_t size, const char *fmt= , va_list args) const char *spec_start =3D fmt; /* For rewinding on error. */ =20 unsigned long long num; - unsigned int base, flags =3D 0; + unsigned int base, flags =3D caller_flags; int width =3D -1, precision =3D -1; - char length_mod =3D 'i'; + char c, length_mod =3D 'i'; =20 /* Put regular characters into the destination. */ if ( *fmt !=3D '%' ) { - PUT(*fmt); - continue; + c =3D *fmt; + goto put_char; } =20 next_flag: /* Process any flags. */ @@ -359,20 +365,21 @@ int vsnprintf(char *buf, size_t size, const char *fmt= , va_list args) continue; =20 case 'c': /* Unsigned char. */ - { - unsigned char c =3D va_arg(args, int); + c =3D va_arg(args, int); =20 if ( !(flags & LEFT) ) while ( --width > 0 ) PUT(' '); =20 + put_char: + if ( (flags & LF_TO_CRLF) && c =3D=3D '\n' ) + PUT('\r'); PUT(c); =20 while ( --width > 0 ) PUT(' '); =20 continue; - } =20 case 's': /* String. */ str =3D fmt_string(str, end, va_arg(args, const char *), diff --git a/include/xtf/libc.h b/include/xtf/libc.h index 66f834b4..f24a631f 100644 --- a/include/xtf/libc.h +++ b/include/xtf/libc.h @@ -37,8 +37,21 @@ int memcmp(const void *s1, const void *s2, size_t n); =20 size_t strnlen(const char *str, size_t max); =20 +/* + * Internal version of vsnprintf(), taking extra control flags. + * + * LF_TO_CRLF causes "\n" to be expanded to "\r\n" in the output buffer. + */ +#define LF_TO_CRLF (1u << 7) int __printf(3, 0) - vsnprintf(char *buf, size_t size, const char *fmt, va_list args); + vsnprintf_internal(char *buf, size_t size, const char *fmt, va_list ar= gs, + unsigned int flags); + +static inline int __printf(3, 0) + vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + return vsnprintf_internal(buf, size, fmt, args, 0); +} =20 int __printf(3, 4) snprintf(char *buf, size_t size, const char *fmt, ...); diff --git a/tests/selftest/main.c b/tests/selftest/main.c index c2f6e727..a5c205ba 100644 --- a/tests/selftest/main.c +++ b/tests/selftest/main.c @@ -340,6 +340,43 @@ static void test_driver_init(void) xtf_failure("Fail: xtf_init_grant_table(2) returned %d\n", rc); } =20 +static void test_vsnprintf_crlf_one(const char *fmt, ...) +{ + va_list args; + + char buf[4]; + int rc; + + va_start(args, fmt); + rc =3D vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + if ( rc !=3D 1 ) + return xtf_failure("Fail: '%s', expected length 1, got %d\n", fmt,= rc); + if ( strcmp(buf, "\n") ) + return xtf_failure("Fail: '%s', expected \"\\n\", got %*ph\n", + fmt, (int)sizeof(buf), buf); + + va_start(args, fmt); + rc =3D vsnprintf_internal(buf, sizeof(buf), fmt, args, LF_TO_CRLF); + va_end(args); + + if ( rc !=3D 2 ) + return xtf_failure("Fail: '%s', expected length 2, got %d\n", fmt,= rc); + if ( strcmp(buf, "\r\n") ) + return xtf_failure("Fail: '%s', expected \"\\r\\n\", got %*ph\n", + fmt, (int)sizeof(buf), buf); +} + +static void test_vsnprintf_crlf(void) +{ + printk("Test: vsnprintf() with CRLF expansion\n"); + + test_vsnprintf_crlf_one("\n"); + test_vsnprintf_crlf_one("%c", '\n'); + test_vsnprintf_crlf_one("%s", "\n"); +} + void test_main(void) { /* @@ -368,6 +405,7 @@ void test_main(void) test_extable_handler(); test_custom_idte(); test_driver_init(); + test_vsnprintf_crlf(); =20 if ( has_xenstore ) test_xenstore(); --=20 2.11.0