당신 의 sprintf 는 안전 합 니까?

2834 단어

snprintf 를 사용 하 는 것 도 안전 하지 않 습 니 다.sprintf, snprintf 는 흔히 볼 수 있 는 len + = sprintf () 의 장면 을 처리 하지 못 해 bug 를 초래 할 수 있 습 니 다.
windows 아래 가 더 나 빠 요. snprintf 는 '\ 0' 의 끝 을 보장 하지 않 습 니 다.그래서 더 안전 한 sprintf 가 필요 합 니 다.(nginx 도 비슷 한 문 제 를 의식 하여 ngx sprintf 를 실현 할 때 인터페이스 에 유사 한 조정 을 했 습 니 다)
설명:
[cpp] view plain copy print ?
//return 0 on fail. return result length on success (may truncate).  
  • //we consider '-1' as a dangerous return value that may cause a lot of bugs.  

  • //'buf' will always ended with '\0', and return value will always be length of the result.  
  • //it's safe to use like: len += safe_sprintf(buf+len, buf_size-len, fmt, ....)  

  • int safe_sprintf(char* buf, int buf_size, char* fmt, ...)  
  •                      __attribute__ ((__format__ (__printf__, 3, 4)));  
  • //return 0 on fail. return result length on success (may truncate).
    //we consider '-1' as a dangerous return value that may cause a lot of bugs.
    //'buf' will always ended with '\0', and return value will always be length of the result.
    //it's safe to use like: len += safe_sprintf(buf+len, buf_size-len, fmt, ....)
    int safe_sprintf(char* buf, int buf_size, char* fmt, ...)
                         __attribute__ ((__format__ (__printf__, 3, 4)));

    실현:
    [cpp] view plain copy print ?
    int safe_sprintf(char* buf, int buf_size, char* fmt, ...)  
  • {  

  •     if (buf == NULL || buf_size <= 0) {  
  •         return 0;  

  •     }  
  •   

  •     va_list ap;  
  •     va_start(ap, fmt);  

  •     int res = vsnprintf(buf, buf_size, fmt, ap);  
  •     va_end(ap);  

  •   
  •     if (res == -1) {  

  •         buf[0] = '\0';  
  •         return 0;  

  •     }  
  •   

  •     if (res >= buf_size) {  
  •         res = buf_size - 1;  

  •         buf[res] = '\0';  
  •     }  

  •   
  •     return res;  

  • }  
    int safe_sprintf(char* buf, int buf_size, char* fmt, ...)
    {
    	if (buf == NULL || buf_size <= 0) {
    		return 0;
    	}
    
    	va_list ap;
    	va_start(ap, fmt);
    	int res = vsnprintf(buf, buf_size, fmt, ap);
    	va_end(ap);
    
    	if (res == -1) {
    		buf[0] = '\0';
    		return 0;
    	}
    
    	if (res >= buf_size) {
    		res = buf_size - 1;
    		buf[res] = '\0';
    	}
    
    	return res;
    }

    주의: Liux 버 전의 vsnprintf 는 '\ 0' 의 끝 을 보장 할 수 있 습 니 다. windows 버 전의 vsnprintf 는 '\ 0' 의 끝 을 보장 할 수 없습니다. 다른 플랫폼 의 vsnprintf 가 '\ 0' 의 끝 을 보장 할 수 있 는 지 는 알 수 없습니다. 모든 플랫폼 에서 안전 하 다 는 것 을 확보 하기 위해 저 는 0 을 부여 할 때 플랫폼 을 구분 하지 않 았 습 니 다. 이미 sprintf 가 되 었 으 니 너무 많은 성능 을 생각 하지 마 세 요.

    좋은 웹페이지 즐겨찾기