O (YAML Ain't Markup Language) tem um recurso que o JSON simplesmente não tem: você pode nomear um valor e reutilizá-lo, em vez de repeti-lo. É uma das maiores razões de um arquivo YAML e seu equivalente em JSON não se parecerem.

A sintaxe

  • Uma âncora &nome rotula um nó.
  • Um alias *nome se refere de volta a ele, inserindo o mesmo valor.
  • Uma merge key <<: *nome mescla as chaves de um mapping ancorado no mapping atual, uma forma comum de compartilhar padrões (defaults).

Então um conjunto base de configurações pode ser definido uma vez com uma âncora e puxado para vários lugares com aliases, mantendo o arquivo (não se repita, do inglês don't repeat yourself). Isso é muito usado em configs de CI e em ferramentas próximas do .

O que a conversão faz com eles

O JSON não tem âncoras, aliases nem merge keys, então um conversor os desreferencia: cada alias é substituído por uma cópia completa do valor para o qual apontava, e cada merge key é expandida nas chaves mescladas de fato. O JSON resultante é correto mas maior, e o compartilhamento se foi. Converter de volta para YAML não reconstrói as âncoras, então um round-trip pelo JSON silenciosamente achata a reutilização em duplicação. Se a compactação importava, isso é uma perda real, não apenas cosmética.

A armadilha de segurança

Como um alias pode apontar para algo que ele próprio contém aliases, o YAML permite expansão exponencial. O clássico ataque "billion laughs" aninha âncoras de modo que um arquivo minúsculo expande para gigabytes ao ser resolvido, esgotando a memória. É por isso que um parser YAML cuidadoso limita a expansão de aliases, e por que converter YAML não confiável não é grátis: a expansão acontece durante a conversão. É a mesma classe de risco de uma expansão de entidade XML, e uma razão para tratar YAML de fontes desconhecidas com a mesma cautela que qualquer outra entrada não confiável.

Um alias é uma referência, e a expansão é onde o custo se esconde

Âncoras e aliases parecem uma conveniência para evitar repetição e, num arquivo de configuração, é exatamente isso que são. O custo só aparece quando aninham.

Um alias que expande para uma estrutura contendo outros aliases multiplica em vez de somar — a mesma aritmética da expansão de entidades em XML, com a mesma consequência: um arquivo pequeno que expande num enorme. É uma classe documentada de negação de serviço em parsers YAML, e não precisa de autor malicioso: uma configuração muito fatorada chega lá por acidente.

A outra surpresa é mais sutil: chaves de merge copiam no ponto de uso, então um valor alterado na âncora depois de o alias ter sido escrito se comporta como o leitor espera, enquanto um valor sobrescrito localmente não compõe como a herança de uma linguagem de programação faria.