(root)/
strace-6.5/
src/
xstring.h
       1  /*
       2   * Copyright (c) 2018-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       3   * Copyright (c) 2021-2022 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #ifndef STRACE_XSTRING_H
      10  # define STRACE_XSTRING_H
      11  
      12  # include <stdarg.h>
      13  # include <stdio.h>
      14  
      15  # include "error_prints.h"
      16  # include "macros.h"
      17  
      18  /**
      19   * Print to static buffer and die on (really unexpected) errors and overflows.
      20   * Shouldn't be used directly; please refer to helper macros xsnprintf and
      21   * xsprintf instead.
      22   *
      23   * @param str    String buffer to print into.
      24   * @param size   Size of the string buffer in bytes.
      25   * @param func   Function name from which this function is called.
      26   * @param argstr Stringified arguments (including format argument).
      27   * @param format Format string.
      28   * @param ...    Format arguments.
      29   * @return       Number of characters printed, excluding terminating null byte
      30   *               (the same as s(n)printf).
      31   */
      32  static inline int ATTRIBUTE_FORMAT((printf, 5, 6))
      33  xsnprintf_(char *str, size_t size, const char *func, const char *argstr,
      34  	   const char *format, ...)
      35  {
      36  	int ret;
      37  	va_list ap;
      38  
      39  	va_start(ap, format);
      40  	ret = vsnprintf(str, size, format, ap);
      41  	va_end(ap);
      42  
      43  	if (ret < 0 || (unsigned int) ret >= size)
      44  		error_msg_and_die("%s: got unexpected return value %d for "
      45  				  "snprintf(buf, %zu, %s)",
      46  				  func, ret, size, argstr);
      47  
      48  	return ret;
      49  }
      50  
      51  /**
      52   * snprintf that dies on (really unexpected) errors and overflows.
      53   *
      54   * @param str_  String buffer to print into.
      55   * @param size_ Size of the string buffer in bytes.
      56   * @param fmt_  Format string.
      57   * @param ...   Format arguments.
      58   */
      59  # define xsnprintf(str_, size_, fmt_, ...) \
      60  	xsnprintf_((str_), (size_), __func__, #fmt_ ", " #__VA_ARGS__, \
      61  		   (fmt_), ##__VA_ARGS__)
      62  
      63  /**
      64   * Print to a character array buffer and die on (really unexpected) errors and
      65   * overflows.  Buffer size is obtained with sizeof().
      66   *
      67   * @param str_  Character array buffer to print into.
      68   * @param fmt_  Format string.
      69   * @param ...   Format arguments.
      70   */
      71  # define xsprintf(str_, fmt_, ...) \
      72  	xsnprintf((str_), sizeof(str_) + MUST_BE_ARRAY(str_), (fmt_), \
      73  		  ##__VA_ARGS__)
      74  
      75  static inline size_t
      76  get_pos_diff_(char *str, size_t size, char *pos, const char *func,
      77  	   const char *call)
      78  {
      79  	if ((str + size) < str)
      80  		error_msg_and_die("%s: string size overflow (%p+%zu) in %s",
      81  				  func, str, size, call);
      82  
      83  	if (pos > (str + size))
      84  		error_msg_and_die("%s: got position (%p) beyond string "
      85  				  "(%p+%zu) in %s",
      86  				  func, pos, str, size, call);
      87  
      88  	if (pos < str)
      89  		error_msg_and_die("%s: got position %p before string %p in %s",
      90  				  func, pos, str, call);
      91  
      92  	return pos - str;
      93  }
      94  
      95  /**
      96   * Helper function for constructing string in a character array by appending
      97   * new formatted parts.  Returns new position.  Fails on error or buffer
      98   * overflow, in line with the rest of x* functions.  Obtains buffer size via
      99   * sizeof(str_).
     100   *
     101   * @param str_  Character array buffer to print into.
     102   * @param pos_  Current position.
     103   * @param fmt_  Format string.
     104   * @param ...   Format arguments.
     105   * @return      New position.
     106   */
     107  # define xappendstr(str_, pos_, fmt_, ...) \
     108  	(xsnprintf((pos_), sizeof(str_) + MUST_BE_ARRAY(str_) - \
     109  		   get_pos_diff_((str_), sizeof(str_), (pos_), __func__, \
     110  				 "xappendstr(" #str_ ", " #pos_ ", " #fmt_ ", " \
     111  				 #__VA_ARGS__ ")"), \
     112  		   (fmt_), ##__VA_ARGS__) + (pos_))
     113  
     114  #endif /* !STRACE_XSTRING_H */