flawopen.com/Segurança de memória/strcpy vs strncpy
strncpy() é mais segura que strcpy()?
Um campo de largura fixa é como uma fileira de espaços rotulados: o último precisa guardar um marcador de fim se o código tratar os bytes como uma string C. strncpy() grava no máximo n bytes, evitando ultrapassar o destino apenas quando n não excede o tamanho real do buffer. Se a origem preencher esse limite, não haverá terminador nulo. Uma função de string posterior poderá ler além do destino à procura do marcador.
char dst[16]; /* 1. Unbounded — classic overflow */ strcpy(dst, src); /* 2. Bounded, but may not terminate. If strlen(src) >= 16, dst has no '\0' and every later strlen/printf reads out of bounds. */ strncpy(dst, src, sizeof(dst)); /* 3. Off-by-one: room for 16 chars plus a terminator = 17 bytes, but dst only holds 16. */ strncpy(dst, src, sizeof(dst)); dst[sizeof(dst)] = '\0'; /* OOB! */
char dst[16]; /* Preferred: snprintf always null-terminates (when size > 0), and tells you about truncation. */ int n = snprintf(dst, sizeof(dst), "%s", src); if (n < 0 || (size_t)n >= sizeof(dst)) { /* truncated — handle it */ return ERR_TOO_LONG; } /* Or strlcpy where available — always terminates, returns the length it tried to create. */ if (strlcpy(dst, src, sizeof(dst)) >= sizeof(dst)) { return ERR_TOO_LONG; }
Para que strncpy foi projetada
Esse comportamento não é defeito: strncpy() foi projetada para sequências de caracteres preenchidas com nulos e de largura fixa, não como cópia geralmente segura de strings C. Se a string de origem for menor que n, a função preenche o destino com bytes nulos até n - 1. Se não houver byte nulo nos primeiros n bytes da origem, copia exatamente n bytes e não termina o destino. Isso pode servir para campos de largura fixa; é perigoso quando o resultado vai para APIs que esperam uma string terminada em nulo.
Quando a origem é menor que n, o preenchimento obrigatório grava até o fim do campo. Em destinos grandes com origens curtas, isso pode fazer mais trabalho do que uma cópia que para no terminador.
Sempre detecte truncamento
Evitar o estouro é apenas metade do trabalho. O truncamento silencioso também cria risco: um host, caminho ou valor de autorização truncado pode mudar de significado. snprintf retorna o tamanho que tentaria escrever; compare esse valor com o tamanho do buffer. Essa semântica de retorno, quando interpretada incorretamente como bytes gravados, também foi relevante no caso Citrix Bleed.
Perguntas frequentes
Elas terminam a string e verificam limites, mas a portabilidade varia: têm bom suporte no Windows e implementação irregular em outros ambientes. Para vários sistemas, snprintf costuma ser a opção mais disponível.
Não. Ela surgiu no OpenBSD e está disponível em BSD e macOS; versões recentes do glibc também a incluem. Verifique os sistemas-alvo em vez de presumir disponibilidade.
Prefira std::string e std::string_view, que gerenciam o tamanho. Use funções C apenas em limites de API que exigem um buffer bruto.