Arquivos de teste de casos-limite — corrompidos, truncados, vazios e com tipo errado

36 arquivos · links diretos · sem anúncios · uso livre

Sem bombas ZIPSem executáveisSem strings de malwareSHA-256 publicadoSeguro para extrair

O resto desta biblioteca responde a "me dê um PNG válido". Esta página responde à pergunta mais difícil: o que o seu código faz com um arquivo truncado, vazio, com nome errado, mentindo sobre o próprio tipo ou carregando dados que não deveria? São esses os uploads que chegam à produção, e eles dão tanto trabalho para montar à mão que a maioria das suítes de teste simplesmente nunca os experimenta.

Todos os arquivos aqui são seguros. Não há zip bombs, entradas de path traversal, executáveis nem strings de teste de malware; o maior arquivo compactado se expande para menos de um megabyte. Os modos de falha são reais, o conteúdo não é perigoso, e o SHA-256 de cada arquivo é publicado para que você possa fixá-lo como fixture.

Comece por dois. O arquivo HTML chamado .jpg mostra se um upload de imagem pode virar cross-site scripting armazenado no seu domínio. O CSV com fórmulas maliciosas mostra se as suas exportações chegam à planilha de um colega como fórmulas ativas. São esses dois que mais encontram bugs reais.

Arquivos vazios e quase vazios

Um upload de zero bytes é, de longe, o caso mais esquecido. Validadores que verificam o tamanho máximo costumam esquecer o mínimo, e um código que lê o primeiro byte antes de verificar o tamanho trava aqui em vez de retornar um erro limpo.

ArquivoO que testaTamanhoBaixar
zero-byte.txtCompletamente vazio. Testa a validação de tamanho mínimo, divisões pelo tamanho e código que lê o primeiro byte antes de verificar se ele existe.0 BBaixar
one-byte.txtUm único caractere. Pequeno demais para conter um cabeçalho válido em qualquer formato, então a detecção de tipo precisa falhar sem quebrar.1 BBaixar
empty-archive.zipUm ZIP estruturalmente válido, sem nenhuma entrada. A extração deve dar certo e não produzir nada, em vez de lançar um erro.22 BBaixar

Arquivos truncados e corrompidos

Estes têm um cabeçalho válido e dados incompletos ou danificados, que é exatamente a cara de um upload interrompido. Um código que confia no cabeçalho e processa o resto em streaming vai falhar aqui, e o ponto onde ele falha mostra se o seu tratamento de erros está onde você imagina.

ArquivoO que testaTamanhoBaixar
truncated.pngAssinatura PNG e IHDR válidos, cortado no meio dos dados da imagem. Os decodificadores geram um erro aqui em vez de devolver uma imagem parcial.4 KBBaixar
corrupt-crc.pngTamanho completo e estrutura correta, mas um byte dentro dos dados da imagem foi invertido e o CRC armazenado não bate mais. Decodificadores rigorosos o rejeitam; os tolerantes devolvem pixels errados.9 KBBaixar
truncated.jpgUm JPEG cortado em 60 por cento, sem o marcador de fim de imagem. Muitos decodificadores devolvem uma imagem parcialmente decodificada em vez de falhar, e vale a pena saber como o seu se comporta.603 BBaixar
truncated.zipO diretório central está cortado, que é a cara do upload de um arquivo compactado interrompido no meio. É o ZIP corrompido mais comum no mundo real.3 KBBaixar
malformed.jsonUma vírgula sobrando no final, uma chave sem aspas e uma chave de fechamento faltando. Testa se o seu parser informa uma posição útil em vez de uma falha genérica.136 BBaixar

Arquivos que mentem sobre o próprio tipo

A extensão diz uma coisa e os bytes dizem outra. Se o seu tratador de upload confia na extensão ou no Content-Type enviado pelo navegador, estes passam. O arquivo HTML chamado .jpg é o que importa: servido de volta com um content type de imagem, é inofensivo; servido como HTML a partir do seu domínio, é cross-site scripting armazenado.

ArquivoO que testaTamanhoBaixar
actually-a-png.jpgUm PNG genuíno com extensão .jpg. Qualquer coisa que escolha o decodificador pela extensão vai entregá-lo ao decodificador errado.9 KBBaixar
actually-html.jpgUm documento HTML com extensão .jpg. Se o seu aplicativo armazena este arquivo e o serve de volta com um content type adivinhado, você tem cross-site scripting armazenado.335 BBaixar

Metadados e privacidade

Uma foto tirada direto do celular informa onde foi feita e qual lado fica para cima. Não remova o primeiro e você vaza a localização dos seus usuários; ignore o segundo e todo retrato aparece de lado. Este arquivo traz os dois, para você verificar se o seu pipeline trata cada um.

ArquivoO que testaTamanhoBaixar
exif-gps-orientation.jpgTraz coordenadas GPS (a CN Tower, em Toronto) e Orientation 6, que significa girar 90 graus no sentido horário para exibir na posição correta. Use-o para verificar tanto se você remove os dados de localização quanto se respeita a rotação.1 KBBaixar

Texto, codificação e quebras de linha

Um byte-order mark que vira um caractere visível na primeira coluna, campos entre aspas com vírgulas e quebras de linha literais, três terminadores de linha diferentes no mesmo arquivo e nenhum terminador no final. Tudo isso é comum nos arquivos que usuários de verdade enviam.

ArquivoO que testaTamanhoBaixar
bom-crlf-quoted.csvUm byte-order mark UTF-8, terminadores CRLF, campos entre aspas contendo vírgulas, aspas duplas escapadas, uma quebra de linha literal dentro de um campo e nomes fora do ASCII. Se o BOM aparecer no cabeçalho da primeira coluna, aí está o bug.180 BBaixar
unicode-torture.txtMarcas combinantes, um espaço de largura zero, um override da direita para a esquerda, caracteres do plano astral e um emoji de bandeira com seis pontos de código. Testa contagem de tamanho, truncamento e normalização.565 BBaixar
mixed-line-endings.txtLF, CRLF e um CR isolado no mesmo arquivo, sem terminador na última linha. Código que conta linhas muitas vezes discorda de si mesmo aqui.107 BBaixar
no-trailing-newline.txtTermina sem quebra de linha. Acrescentar conteúdo a este arquivo sem verificar gera dois registros unidos em um só.48 BBaixar

Nomes de arquivo difíceis

O teste está no nome, não no conteúdo. Nomes longos estouram colunas de banco de dados e limites do sistema de arquivos; nomes fora do ASCII quebram cabeçalhos Content-Disposition, o escape de URLs e a diferença entre Unicode composto e decomposto no macOS.

ArquivoO que testaTamanhoBaixar
文件名-with spaces-🌲.txtCaracteres chineses, espaços e um emoji no nome do arquivo. Testa a codificação do Content-Disposition, o escape de URLs e a normalização de Unicode decomposto do macOS.194 BBaixar

Limites estruturais e de recursos

Arquivos válidos que são incômodos, e não quebrados: um arquivo compactado com dez mil entradas, JSON aninhado mais fundo do que a maioria dos parsers permite por padrão e um arquivo compactado criptografado. Nenhum deles é um ataque; são os formatos que fazem uma implementação ingênua ficar sem algum recurso.

ArquivoO que testaTamanhoBaixar
many-entries-10000.zipDez mil entradas pequenas, com menos de 1 MB descompactado no total. Testa a leitura do diretório central e o custo por entrada. Propositalmente, não é uma zip bomb.1.6 MBBaixar
deeply-nested.json512 níveis de aninhamento. JSON válido, mas mais profundo do que muitos parsers permitem por padrão, e profundo o bastante para esgotar a pilha de um parser recursivo.3 KBBaixar
encrypted-password-test.zipCriptografado com ZipCrypto; a senha é test. A extração sem senha deve falhar de forma limpa em vez de produzir lixo.292 BBaixar

Injeção de fórmulas em planilhas

Uma célula de CSV que começa com =, +, - ou @ é interpretada como fórmula quando o arquivo é aberto no Excel, no Planilhas Google ou no LibreOffice. Se o seu aplicativo exporta para CSV texto fornecido por usuários sem escapar esses prefixos, você está entregando a entrada deles como fórmulas executáveis. As cargas daqui calculam apenas aritmética inofensiva.

ArquivoO que testaTamanhoBaixar
formula-injection.csvCélulas que começam com =, +, - e @, que os aplicativos de planilha tratam como fórmulas. As cargas calculam apenas aritmética inofensiva, e uma delas monta um link para este site. Nada executa comandos.189 BBaixar

Modelos 3D: malhas vazias, quebradas e enganosas

Código de malhas costuma presumir um modelo fechado, de tamanho razoável, com a orientação correta dos triângulos e pelo menos um triângulo. Os usuários enviam todo o resto. Estes cobrem a malha vazia, triângulos de área zero e invertidos, uma malha não manifold, coordenadas grandes ou pequenas demais para o float32 lidar bem, um GLB cortado no meio do upload, um STL cujo cabeçalho mente, um GLB fingindo ser STL e o STL binário que engana a verificação clássica “começa com solid, então é ASCII”. Eles ficam na pasta 3D; os exemplos 3D válidos estão na categoria de modelos 3D.

ArquivoO que testaTamanhoBaixar
empty-mesh-zero-triangles.stlUm STL binário estruturalmente válido: o cabeçalho de 80 bytes e uma contagem de 0 triângulos, e nada mais (84 bytes). Código de caixa delimitadora, centralização e miniaturas muitas vezes divide por zero ou acessa um array vazio aqui.84 BBaixar
empty-scene-no-meshes.glbUm glTF 2.0 binário válido, com uma cena e um nó vazio, mas sem malhas, buffers ou materiais. Ele passa no validador da Khronos. Os visualizadores devem mostrar uma cena vazia, e não lançar um erro.276 BBaixar
degenerate-triangles.stlUm cubo de 10 mm mais seis triângulos de área zero: vértices repetidos, pontos colineares e uma lasca menor que o epsilon. O cálculo das normais divide por um comprimento zero aqui, e é daí que vêm as normais NaN.984 BBaixar
flipped-normals-inside-out.stlUm cubo de 10 mm com todos os triângulos orientados no sentido horário e as normais armazenadas apontando para dentro. Ele aparece preto ou invisível com o descarte de faces traseiras, e o volume com sinal é negativo.684 BBaixar
non-manifold-open-box-and-fins.stlUma caixa sem a tampa (uma borda aberta) mais duas aletas que compartilham, cada uma, uma aresta com outras duas faces. Não pode ser impressa como está; fatiadores e ferramentas de reparo devem sinalizar os dois problemas.684 BBaixar
huge-coordinates-1e7.stlUm cubo de 100 unidades centrado a dez milhões de unidades da origem. Nessa magnitude, o float32 só consegue representar números inteiros, então aparecem problemas de precisão, de plano distante da câmera e de enquadramento automático.684 BBaixar
tiny-scale-1e-6.stlUm cubo com um milionésimo de unidade de largura. Lido em milímetros, tem um micrômetro: testa verificações de tamanho mínimo, a adivinhação de unidades e qualquer epsilon usado para mesclar vértices.684 BBaixar
extreme-float-values.stlCoordenadas de vértices em ±3.0e38, perto do máximo do float32, e um triângulo formado por valores subnormais de 1e-40. Não há NaN nem Infinity no arquivo, mas calcular o tamanho da caixa delimitadora em float32 estoura para Infinity.234 BBaixar
truncated.glbOs primeiros 60 por cento de um GLB texturizado válido. O cabeçalho ainda declara o tamanho completo e o chunk BIN termina antes da hora, que é a cara do upload interrompido de um GLB.80 KBBaixar
wrong-triangle-count-header.stlUm STL binário cujo contador uint32 diz 1.000 triângulos, enquanto o arquivo tem 12. Um leitor que confia no contador lê além do fim; um rigoroso rejeita o arquivo porque 84 + 50 × 1.000 não é igual ao tamanho dele.684 BBaixar
actually-a-glb.stlUm GLB genuíno e válido (começa com os bytes glTF) salvo com extensão .stl. Qualquer coisa que escolha o parser pela extensão vai entregá-lo ao parser de STL.21 KBBaixar
binary-stl-header-starts-with-solid.stlUm STL binário válido cujo cabeçalho de texto livre começa com a palavra solid, como vários exportadores reais gravam. Detectar STL ASCII por esse prefixo manda este arquivo para o parser errado; compare o tamanho com a contagem de triângulos.684 BBaixar
obj-missing-mtl.objUm OBJ válido em todo o resto, cuja linha mtllib aponta para um arquivo de material que não existe. A geometria deve carregar mesmo assim, com um material padrão e um aviso, e não falhar.914 BBaixar
obj-negative-indices.objUm OBJ válido cujas faces usam índices negativos e relativos (f -3 -2 -1), o que o formato permite. Muitos parsers escritos à mão só aceitam índices positivos.675 BBaixar
立方体 cube-modèle-🧊.stlUm cubo válido de 10 mm cujo nome de arquivo mistura caracteres chineses, uma letra acentuada, um espaço e um emoji. Testa o Content-Disposition, a codificação de URLs e as chaves de armazenamento em uploads de modelos.684 BBaixar

Um checklist rápido para o tratamento de uploads

  1. Verifique um tamanho mínimo, além do máximo. Uploads de zero byte são o caso esquecido com mais frequência.
  2. Determine o tipo pelos bytes, nunca pela extensão nem pelo content type enviado pelo navegador. Os dois são controlados pelo atacante.
  3. Sirva os uploads dos usuários a partir de um domínio separado, ou com Content-Disposition: attachment e X-Content-Type-Options: nosniff, para que um arquivo que acabe sendo HTML não possa ser executado na sua origem.
  4. Remova o EXIF antes de publicar uma imagem e aplique a tag de orientação antes de removê-lo.
  5. Escape =, +, - e @ no início do texto do usuário ao gravá-lo em CSV.
  6. Defina limites explícitos para o número de entradas em arquivos compactados, o tamanho total descompactado e a profundidade de recursão do parser, e retorne um erro claro quando algum for atingido.
  7. Decida o que deve acontecer com um arquivo enviado pela metade e teste isso com os arquivos truncados daqui, em vez de supor.

Perguntas frequentes

Esses arquivos são perigosos?

Não. Não há zip bombs, entradas de path traversal, executáveis, macros nem strings de teste de malware. O maior arquivo se expande para menos de um megabyte. Os modos de falha são reais — uma imagem truncada está mesmo truncada —, mas nada aqui ataca a máquina que o abre. As fórmulas na planilha calculam uma conta inofensiva em vez de executar um comando.

Para que serve o arquivo HTML com extensão .jpg?

É o arquivo mais valioso do pacote. Se a sua aplicação o aceita como imagem, o armazena e depois o devolve com um content type deduzido pelo conteúdo, o navegador o renderiza como uma página no seu domínio. Isso é cross-site scripting armazenado entregue por um upload de imagem. Aceitar o arquivo não é problema; devolvê-lo como HTML é.

Por que o CSV tem células que começam com sinal de igual?

Porque o Excel, o Planilhas Google e o LibreOffice interpretam uma célula que começa com =, +, - ou @ como fórmula. Se a sua aplicação exporta para CSV texto fornecido pelo usuário sem escapar esses prefixos, o que alguém digitou num formulário chega à planilha de um colega como fórmula ativa. A correção é prefixar essas células com um apóstrofo ou colocá-las entre aspas na exportação.

A foto tem mesmo coordenadas de GPS?

Sim — a CN Tower, em Toronto, a 43,6426 norte e 79,3871 oeste, além da altitude. Ela também traz Orientation 6, o que significa que o visualizador deve girá-la 90 graus no sentido horário para exibi-la em pé. Juntas, essas duas coisas cobrem o que todo pipeline de imagens precisa acertar: remover os dados de localização antes de publicar e respeitar a rotação para que fotos em retrato não fiquem de lado.

Posso usar esses arquivos numa suíte de testes automatizados?

Sim, é para isso que eles servem. Todos os arquivos são determinísticos, o SHA-256 de cada um é publicado aqui, e os links diretos têm cache de longa duração e cabeçalhos CORS abertos. Fixe o hash no seu teste e você saberá na hora se um fixture mudar.

Encontrou um problema ou algo que poderia ser melhor? Lemos todas as mensagens e corrigimos rápido.

Precisa de arquivos válidos?

A maioria dos testes precisa de um arquivo que funcione. Também publicamos esses — imagens, vídeos, áudios, documentos, arquivos compactados, dados, fontes e modelos 3D reais, em tamanhos exatos e com hashes publicados.