简体   繁体   English

使用指向char的指针时如何使用snprintf

[英]How to use snprintf when using a pointer to char

Right now I'm using sprintf but want to change to snprintf .现在我正在使用sprintf但想更改为snprintf

My question is, what is the best way to secure that I'm not doing a buffer overflow, when I'm doing something like the code below using pointer:我的问题是,当我使用指针执行类似以下代码的操作时,确保我不执行缓冲区溢出的最佳方法是什么:

This is a quick example of the code, in my code the string_pos += get_line_to_buffer(&string[string_pos]);这是代码的一个快速示例,在我的代码中string_pos += get_line_to_buffer(&string[string_pos]); is called multiple times.被多次调用。 So I'm gonna add alot of data to the buffer and therefore I want to make sure I'm not writing too much.所以我要向缓冲区添加大量数据,因此我想确保我不会写太多。

int main(void){
    char string[50];
    size_t string_pos = 0;

    string_pos += get_line_to_buffer(&string[string_pos]);
}

static size_t get_line_to_buffer(char *buffer){
    char* p = buffer;

    p += sprintf(p, "%d,%s,%s,%lu", version, fileName, Id, timestamp);
    p += sprintf(p, ",%d,%d,%f", noOfObs, frequency, sum);
    p += sprintf(p, ",%f,%f", latitude, longitude);
    p += sprintf(p, ",%f,%d", speed, errorCode);
    p += sprintf(p, "\r\n");

    return p - buffer;
}

Read carefully documentation of snprintf (and/or the Linux one, snprintf(3) ).仔细阅读snprintf文档(和/或 Linux文档snprintf(3) )。 Notice that it could fail by returning a negative value.请注意,它可能会因返回负值而失败。 And you could be interested by its %n .你可能会对它的%n感兴趣。

You need to know the size of the buffer.您需要知道缓冲区的大小。 A good way is to pass it as a second argument to your get_line_to_buffer function:一个好方法是将它作为第二个参数传递给get_line_to_buffer函数:

ssize_t get_line_to_buffer(char *buffer, size_t siz) {
  char* p = buffer;
  char* start = buffer;
  char* end = buffer + siz;
  int n = 0;
  if (p < end)
     n = snprintf(p, siz, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
  else
     n = snprintf(NULL, 0, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
  if (n<0) return -1;
  p += n, siz -= n;
  if (siz<0) return -1;
  if (p < end)
     n = snprintf(p, siz, ",%d,%d,%f", noOfObs, frequency, sum);
  else
      n = snprintf(NULL, 0, ",%d,%d,%f", noOfObs, frequency, sum);
  if (n<0) return -1;
  p += n; siz -= n;
  return p - start;
}

Actually, you could consider using asprintf(3) if your system has it.实际上,如果您的系统有asprintf(3) ,您可以考虑使用它。

And you might instead open a in-memory stream with fmemopen(3) or open_memstream(3) and use fprintf on it.您可以改为使用fmemopen(3)open_memstream(3)打开内存流并在其上使用fprintf

BTW, you might simply do a single snprintf but split its format control string in several physical lines:顺便说一句,您可能只执行一个snprintf但将其格式控制字符串拆分为几行:

int n = snprintf(p, siz,  
                 "%d, %s, %s, %lu"
                 ",%d,%d,%f",
                 version, fileName, Id, timestamp,
                 noOfObs, frequency, sum);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM