On Wed, 2021-03-24 at 09:52 -0700, Joe Perches wrote:
> On Wed, 2021-03-24 at 17:42 +0100, Arnd Bergmann wrote:
> > On Wed, Mar 24, 2021 at 3:20 PM Joe Perches <j...@perches.com> wrote:
> []
> > > > diff --git a/drivers/gpu/drm/imx/imx-ldb.c 
> > > > b/drivers/gpu/drm/imx/imx-ldb.c
> > > []
> > > > @@ -197,6 +197,12 @@ static void imx_ldb_encoder_enable(struct 
> > > > drm_encoder *encoder)
> > > >       int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
> > > >       int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, 
> > > > encoder);
> > > > 
> > > > +     if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) {
> > > > +             dev_warn(ldb->dev, "%s: invalid mux %d\n",
> > > > +                      __func__, ERR_PTR(mux));
> > > 
> > > This does not compile without warnings.
> > > 
> > > drivers/gpu/drm/imx/imx-ldb.c: In function ‘imx_ldb_encoder_enable’:
> > > drivers/gpu/drm/imx/imx-ldb.c:201:22: warning: format ‘%d’ expects 
> > > argument of type ‘int’, but argument 4 has type ‘void *’ [-Wformat=]
> > >   201 |   dev_warn(ldb->dev, "%s: invalid mux %d\n",
> > >       |                      ^~~~~~~~~~~~~~~~~~~~~~
> > > 
> > > If you want to use ERR_PTR, the %d should be %pe as ERR_PTR
> > > is converting an int a void * to decode the error type and
> > > emit it as a string.
> > 
> > Sorry about that.
> > 
> > I decided against using ERR_PTR() in order to also check for
> > positive array overflow, but the version I tested was different from
> > the version I sent.
> > 
> > v3 coming.
> 
> Thanks.  No worries.
> 
> Up to you, vsprintf would emit the positive mux as a funky hashed
> hex value by default if you use ERR_PTR with mux > ARRAY_SIZE so
> perhaps %d without the ERR_PTR use makes the most sense.
> 
> 

Maybe it's better to output non PTR_ERR %pe uses as decimal so this
sort of code would work.
---
 lib/vsprintf.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3600db686fa4..debdd1c62038 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -619,19 +619,23 @@ static char *string_nocheck(char *buf, char *end, const 
char *s,
        return widen_string(buf, len, end, spec);
 }
 
-static char *err_ptr(char *buf, char *end, void *ptr,
-                    struct printf_spec spec)
+static noinline_for_stack
+char *err_ptr(char *buf, char *end, void *ptr, struct printf_spec spec)
 {
        int err = PTR_ERR(ptr);
-       const char *sym = errname(err);
 
-       if (sym)
-               return string_nocheck(buf, end, sym, spec);
+       if (IS_ERR(ptr)) {
+               const char *sym = errname(err);
+
+               if (sym)
+                       return string_nocheck(buf, end, sym, spec);
+       }
 
        /*
-        * Somebody passed ERR_PTR(-1234) or some other non-existing
-        * Efoo - or perhaps CONFIG_SYMBOLIC_ERRNAME=n. Fall back to
-        * printing it as its decimal representation.
+        * Somebody passed ERR_PTR(-1234) or some other non-existing -E<FOO>
+        * or perhaps CONFIG_SYMBOLIC_ERRNAME=n
+        * or perhaps a positive number like an array index
+        * Fall back to printing it as its decimal representation.
         */
        spec.flags |= SIGN;
        spec.base = 10;
@@ -2407,9 +2411,7 @@ char *pointer(const char *fmt, char *buf, char *end, void 
*ptr,
        case 'x':
                return pointer_string(buf, end, ptr, spec);
        case 'e':
-               /* %pe with a non-ERR_PTR gets treated as plain %p */
-               if (!IS_ERR(ptr))
-                       break;
+               /* %pe with a non-ERR_PTR(ptr) gets treated as %ld */
                return err_ptr(buf, end, ptr, spec);
        case 'u':
        case 'k':

---


Reply via email to