![Es sprintf(búfer, "%s […]", buffer, […]) ¿a salvo? 1 avatar de usuario](https://www.revivemyvote.com/wp-content/uploads/Es-sprintfbufer-s-…-buffer-…-¿a-salvo.jpeg)
pablo pescador
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ás que buffer
es tanto la salida como la primera entrada.
Aparte de la posibilidad obvia de un desbordamiento de búfer, creo que no hay garantía de que el búfer no cambie entre el inicio y el final de la función (es decir, no hay garantía de cuál será el estado del búfer durante la ejecución de la función). La firma de sprintf especifica además que la cadena de destino es restrict
edición
También recuerdo un informe de un escritura especulativa en memcpy, y no veo ninguna razón por la que alguna biblioteca de C pueda hacer lo mismo en un sprintf. En este caso, por supuesto, estaría escribiendo a su fuente. Entonces ¿Es este comportamiento seguro?
FYI, 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.
![Es sprintf(búfer, "%s […]", buffer, […]) ¿a salvo? 2 avatar de usuario](https://www.revivemyvote.com/wp-content/uploads/Es-sprintfbufer-s-…-buffer-…-¿a-salvo.png)
Karl Voigtland
Desde el documentación de glibc sprintf():
El comportamiento de esta función no está definido si la copia tiene lugar entre objetos que se superponen; por ejemplo, si s también se proporciona como argumento para imprimir bajo el control de la conversión ‘%s’.
Puede ser seguro en una implementación particular; pero no podías contar con que fuera portátil.
Tampoco estoy seguro de que su propuesta sea segura en todos los casos. Todavía podría estar superponiendo búferes. Es tarde y mi esposa me está molestando, pero creo que aún podría tener el caso en el que desea usar la cadena original nuevamente en la cadena concatenada y está sobrescribiendo el carácter nulo y, por lo tanto, es posible que la implementación de sprintf no sepa dónde se reutilizó. extremos de cuerda.
Es posible que desee seguir con 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 buffer
será lo primero que va a entrar buffer
(de nuevo, inútil), así que deberías usar strcat()
en cambio para obtener el [almost] mismo efecto.
Pero, si está tratando de combinar strcat()
con las posibilidades formativas de sprintf()
puedes intentar esto:
sprintf(&buffer[strlen(buffer)], " <input type="file" name="%s" />\r\n", id);
Si desea concatenar texto formateado al 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 al votar negativamente (“¡Esto no es seguro! ¡Puedes desbordar el búfer!”), Solo estoy abordando una forma razonable de construir una cadena formateada en C/C++.
Incluso si es a salvo (no se bloqueará, etc.) Puedo imaginarlo generando un resultado diferente al esperado.
– nadie
16 de agosto de 2009 a las 3:08
@AndrewMedico ¿Cómo es eso?
– gato
27/09/2016 a las 21:49