sprintf snprintf pro ejemplo c printf c-strings

c - snprintf - sprintf r



¿Es seguro el sprintf(búfer, "% s[...]", búfer,[...])? (3)

Vi el uso de este patrón para concatenar en una cadena en un código en el que estaba trabajando:

sprintf(buffer, "%s <input type=''file'' name=''%s'' />/r/n", buffer, id); sprintf(buffer, "%s</td>", buffer);

y estoy bastante seguro de que no es seguro C. Notará que el buffer es tanto la salida como la primera entrada.

Aparte de la posibilidad obvia de un desbordamiento del búfer , creo que no hay ninguna garantía de que el búfer no cambie entre el inicio y el final de la función (es decir, no hay ninguna garantía de cuál será el estado del búfer durante el ejecución de la función). La firma de sprintf además especifica que la cadena objetivo está restrict .

También recuerdo un informe de una escritura especulativa en memcpy , y no veo ninguna razón por la que alguna biblioteca C pueda hacer lo mismo en un sprintf. En este caso, por supuesto, estaría escribiendo a su fuente. Entonces, ¿ es seguro este comportamiento?

Para tu información, te propuse:

char *bufEnd = buffer + strlen(buffer); /* sprintf returns the number of f''d and print''d into the s */ bufEnd += sprintf(bufEnd, " <input type=''file'' name=''%s'' />/r/n", id);

para reemplazar esto.


De la documentación de glibc sprintf () :

El comportamiento de esta función no está definido si la copia se realiza entre objetos que se superponen, por ejemplo, si s también se presenta como un argumento para imprimir bajo el control de la conversión ''% s''.

Puede ser seguro en una implementación particular; Pero no se podía contar con que fuera portátil.

Tampoco estoy seguro de que su propuesta sea segura en todos los casos. Todavía podrías estar superponiendo buffers. Es tarde y mi esposa me está molestando, pero creo que aún podría tener el caso en el que quiera usar la cadena original nuevamente en la cadena concatenada y esté sobrescribiendo el carácter nulo, por lo que es posible que la implementación de sprintf no sepa dónde se reutilizó. cadena termina.

Es posible que solo desee mantener un snprint () en un búfer temporal, luego strncat () en el búfer original.


En este caso específico, va a funcionar porque la cadena en el buffer será la primera cosa que se ingresará en el buffer (de nuevo, inútil), por lo que debe usar strcat() lugar de obtener el mismo efecto.

Pero, si estás tratando de combinar strcat() con las posibilidades de sprintf() de sprintf() , puedes intentar esto:

sprintf(&buffer[strlen(buffer)], " <input type=''file'' name=''%s'' />/r/n", id);


Si desea concatenar texto formateado hasta el final de un búfer usando printf (), le recomiendo que use un número entero para realizar un seguimiento de la posición final.

int i = strlen(buffer); i += sprintf(&buffer[i], " <input type=''file'' name=''%s'' />/r/n", id); i += sprintf(&buffer[i], "</td>");

o:

int i = strlen(buffer); i += sprintf(&buffer[i], " <input type=''file'' name=''%s'' />/r/n", id); strcat(&buffer[i], "</td>");

Y antes de que la gente se vuelva loca a la baja al votar esto ("¡Esto no es seguro! ¡Puedes sobrepasar el búfer!"), Simplemente estoy tratando una forma razonable de crear una cadena con formato en C / C ++.