]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - lib/vsprintf.c
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszer...
[linux.git] / lib / vsprintf.c
index 01c3957b2de621ae21fed6162058c37f801ff526..77ee6ced11b17a411d95f266faeaaf7dba309d4f 100644 (file)
@@ -42,7 +42,6 @@
 #include "../mm/internal.h"    /* For the trace_print_flags arrays */
 
 #include <asm/page.h>          /* for PAGE_SIZE */
-#include <asm/sections.h>      /* for dereference_function_descriptor() */
 #include <asm/byteorder.h>     /* cpu_to_le16 */
 
 #include <linux/string_helpers.h>
@@ -1834,7 +1833,8 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
  *
  * - 'x' For printing the address. Equivalent to "%lx".
  *
- * ** Please update also Documentation/printk-formats.txt when making changes **
+ * ** When making changes please also update:
+ *     Documentation/core-api/printk-formats.rst
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1862,10 +1862,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
        switch (*fmt) {
        case 'F':
        case 'f':
-               ptr = dereference_function_descriptor(ptr);
-               /* Fallthrough */
        case 'S':
        case 's':
+               ptr = dereference_symbol_descriptor(ptr);
+               /* Fallthrough */
        case 'B':
                return symbol_string(buf, end, ptr, spec, fmt);
        case 'R':
@@ -2194,7 +2194,7 @@ set_precision(struct printf_spec *spec, int prec)
  *  - ``%n`` is unsupported
  *  - ``%p*`` is handled by pointer()
  *
- * See pointer() or Documentation/printk-formats.txt for more
+ * See pointer() or Documentation/core-api/printk-formats.rst for more
  * extensive description.
  *
  * **Please update the documentation in both places when making changes**
@@ -2516,29 +2516,34 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
 {
        struct printf_spec spec = {0};
        char *str, *end;
+       int width;
 
        str = (char *)bin_buf;
        end = (char *)(bin_buf + size);
 
 #define save_arg(type)                                                 \
-do {                                                                   \
+({                                                                     \
+       unsigned long long value;                                       \
        if (sizeof(type) == 8) {                                        \
-               unsigned long long value;                               \
+               unsigned long long val8;                                \
                str = PTR_ALIGN(str, sizeof(u32));                      \
-               value = va_arg(args, unsigned long long);               \
+               val8 = va_arg(args, unsigned long long);                \
                if (str + sizeof(type) <= end) {                        \
-                       *(u32 *)str = *(u32 *)&value;                   \
-                       *(u32 *)(str + 4) = *((u32 *)&value + 1);       \
+                       *(u32 *)str = *(u32 *)&val8;                    \
+                       *(u32 *)(str + 4) = *((u32 *)&val8 + 1);        \
                }                                                       \
+               value = val8;                                           \
        } else {                                                        \
-               unsigned long value;                                    \
+               unsigned int val4;                                      \
                str = PTR_ALIGN(str, sizeof(type));                     \
-               value = va_arg(args, int);                              \
+               val4 = va_arg(args, int);                               \
                if (str + sizeof(type) <= end)                          \
-                       *(typeof(type) *)str = (type)value;             \
+                       *(typeof(type) *)str = (type)(long)val4;        \
+               value = (unsigned long long)val4;                       \
        }                                                               \
        str += sizeof(type);                                            \
-} while (0)
+       value;                                                          \
+})
 
        while (*fmt) {
                int read = format_decode(fmt, &spec);
@@ -2554,7 +2559,10 @@ do {                                                                     \
 
                case FORMAT_TYPE_WIDTH:
                case FORMAT_TYPE_PRECISION:
-                       save_arg(int);
+                       width = (int)save_arg(int);
+                       /* Pointers may require the width */
+                       if (*fmt == 'p')
+                               set_field_width(&spec, width);
                        break;
 
                case FORMAT_TYPE_CHAR:
@@ -2576,7 +2584,27 @@ do {                                                                     \
                }
 
                case FORMAT_TYPE_PTR:
-                       save_arg(void *);
+                       /* Dereferenced pointers must be done now */
+                       switch (*fmt) {
+                       /* Dereference of functions is still OK */
+                       case 'S':
+                       case 's':
+                       case 'F':
+                       case 'f':
+                               save_arg(void *);
+                               break;
+                       default:
+                               if (!isalnum(*fmt)) {
+                                       save_arg(void *);
+                                       break;
+                               }
+                               str = pointer(fmt, str, end, va_arg(args, void *),
+                                             spec);
+                               if (str + 1 < end)
+                                       *str++ = '\0';
+                               else
+                                       end[-1] = '\0'; /* Must be nul terminated */
+                       }
                        /* skip all alphanumeric pointer suffixes */
                        while (isalnum(*fmt))
                                fmt++;
@@ -2728,11 +2756,39 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
                        break;
                }
 
-               case FORMAT_TYPE_PTR:
-                       str = pointer(fmt, str, end, get_arg(void *), spec);
+               case FORMAT_TYPE_PTR: {
+                       bool process = false;
+                       int copy, len;
+                       /* Non function dereferences were already done */
+                       switch (*fmt) {
+                       case 'S':
+                       case 's':
+                       case 'F':
+                       case 'f':
+                               process = true;
+                               break;
+                       default:
+                               if (!isalnum(*fmt)) {
+                                       process = true;
+                                       break;
+                               }
+                               /* Pointer dereference was already processed */
+                               if (str < end) {
+                                       len = copy = strlen(args);
+                                       if (copy > end - str)
+                                               copy = end - str;
+                                       memcpy(str, args, copy);
+                                       str += len;
+                                       args += len;
+                               }
+                       }
+                       if (process)
+                               str = pointer(fmt, str, end, get_arg(void *), spec);
+
                        while (isalnum(*fmt))
                                fmt++;
                        break;
+               }
 
                case FORMAT_TYPE_PERCENT_CHAR:
                        if (str < end)