


Encontrar bugs reais em patches de sistemas de baixo nível, sem implicar com estilo
Use ao revisar patches de sistemas de baixo nível, como drivers ou bibliotecas de rede. Segue memória, locks e caminhos de erro, verifica inteiros, threads, criptografia e mudanças de API e relata só problemas corrigíveis; estilo, só com muita certeza.
Para usar estas regras de IA
## Relatar possíveis bugs mesmo com dúvida e estilo só com muita certeza
Considere os defeitos de correção os achados de maior valor. Relate um possível erro de correção quando a confiança for de 50% ou mais e declare a incerteza quando as evidências estiverem incompletas. Vale a pena apontar um possível uso após liberação, vazamento de recursos, condição de corrida ou violação de limites, mesmo quando for necessária uma confirmação adicional.
Aplique um limite diferente aos achados de estilo, formatação e processo:
- Relate-os somente quando a confiança for superior a 80%.
- Omita tudo o que você considerar, ao final, correto, aceitável ou inofensivo.
- Nunca apresente uma preocupação para depois contradizê-la no mesmo achado.
- Sempre que possível, use uma frase que indique uma ação em cada comentário.
Analise cada alteração pelo comportamento que ela própria produz. Não deduza, a partir de uma diferença isolada, a ordem de uma série de alterações, as dependências de compilação entre alterações nem as circunstâncias do colaborador. Em uma série, omita alterações sem problemas em vez de resumi-las como livres de falhas.
## Seguir alocações e caminhos de erro em busca de vazamentos e mau uso
Para cada alocação, identificador aberto, bloqueio adquirido ou objeto parcialmente inicializado, rastreie todas as ramificações posteriores. Verifique se retornos antecipados e rótulos de limpeza mantêm liberações correspondentes, a ordem correta e os códigos de erro preservados.
Priorize:
- Acesso após liberação, liberação dupla, desreferência de ponteiro nulo e leituras alcançáveis de valores não inicializados.
- Vazamentos de memória, descritores, conexões de rede, bloqueios ou membros construídos parcialmente.
- Ausência de verificações de falha em operações que realmente podem falhar.
- Valores de retorno incorretos, estado de erro descartado, condições invertidas e limites deslocados em uma posição.
- Um valor sobrescrito incondicionalmente antes de sua primeira leitura.
- Reutilização do mesmo contador de laço em laços aninhados.
- Acumulação de um contador que atribui uma amostra em vez de somá-la.
Diferencie contadores incrementais, medidores e atribuições iniciais. Não sinalize um retorno não verificado apenas porque uma função tem um tipo de retorno inteiro quando a plataforma compatível documenta que essa chamada não pode falhar com argumentos válidos.
## Verificar larguras de inteiros e tamanhos de pacotes
Analise a aritmética na largura dos operandos, não apenas na largura do destino:
- Amplie pelo menos um operando antes da multiplicação quando o resultado precisar de um tipo mais largo.
- Use um literal ou operando com a mesma largura do destino antes de deslocá-lo para uma máscara de bits larga.
- Amplie valores sem sinal estreitos antes de um deslocamento usado em aritmética de ponteiros ou em um resultado largo.
- Não altere deslocamentos com resultado estreito quando todo o intervalo couber e não houver um contexto mais largo.
- Limite toda travessia de cadeias ou índices controlada por entradas do sistema convidado, de pacotes, de dispositivos ou da API.
Respeite a propriedade ao liberar lotes de objetos de pacotes ou descritores. Uma primitiva em massa que pressupõe um único alocador ou conjunto de memória não é segura para vetores cujos elementos podem ter origens diferentes; use uma rota de liberação que reconheça o conjunto de memória, a menos que o contrato da rota rápida comprove propriedade uniforme.
Mantenha o tamanho da carga útil do protocolo separado do tamanho total do quadro. Calcule a sobrecarga de enquadramento com base nas capacidades do dispositivo, e não em uma constante universal, e leia a configuração atual canônica após a preparação, em vez de um campo de solicitação obsoleto.
Quando um quadro não couber em um único buffer de recepção, a implementação deverá habilitar uma rota compatível com vários segmentos ou rejeitar a configuração. Verifique isso novamente durante a configuração inicial, a preparação da fila e as alterações de tamanho em tempo de execução, e selecione a função de recepção com base tanto no modo configurado quanto no requisito real de tamanho.
## Verificar se dados compartilhados usam atômicos ou locks, e não volatile
Não aceite `volatile` como sincronização entre fluxos de execução. O estado mutável compartilhado exige operações atômicas ou um bloqueio adequado; `volatile` apenas restringe os acessos do compilador e não fornece atomicidade nem ordenação de memória.
Escolha a ordenação mais fraca que mantenha a correção:
- Ordenação relaxada para estatísticas e sinalizadores independentes que não publicam dados relacionados.
- Armazenamentos com liberação e carregamentos com aquisição para relações de publicação e consumo.
- Ordenação de aquisição e liberação para operações de leitura, modificação e escrita que consomem e publicam estado.
- Consistência sequencial somente quando operações atômicas independentes exigirem uma única ordem global.
Prefira especificar a ordenação na operação atômica em vez de usar uma barreira independente. Uma barreira só é apropriada quando precisa ordenar um grupo maior de acessos não atômicos.
Permita `volatile` em registradores de hardware e em outros acessos realmente voltados a dispositivos. Para mutexes, condições, barreiras ou bloqueios de leitura e escrita colocados em memória compartilhada entre processos, exija inicialização compartilhada entre processos; não a exija para memória privativa de um processo. Prefira primitivas de sincronização projetadas para memória compartilhada quando o comportamento de espera delas for adequado ao caso de uso.
## Revisar criptografia só quando o patch lida com chaves ou segredos
Aplique verificações criptográficas somente quando a alteração lidar com chaves, valores de uso único, material de autenticação ou código de protocolos de segurança.
- Compare etiquetas de autenticação, resumos, MAC ou valores de integridade influenciados por um invasor usando uma primitiva de igualdade em tempo constante.
- Preserve a semântica de igualdade ao substituir uma comparação comum de bytes.
- Apague chaves, programações expandidas de chaves, segredos de sessão e materiais semelhantes com uma operação que não possa ser eliminada por otimização antes de liberá-los.
- Gere chaves, vetores de inicialização e valores de uso único com uma fonte aleatória criptograficamente segura.
Não sinalize comparações comuns de identificadores de algoritmos, comprimentos, capacidades ou chaves de consulta. Não afirme que houve reutilização de um valor de uso único com base em uma alteração estática quando a reutilização for uma propriedade do tempo de execução que a diferença não pode comprovar.
## Manter a API da biblioteca simples e versionar mudanças de ABI incompatíveis
Projete uma biblioteca reutilizável como um serviço semelhante a um compilador: crie um identificador de acesso, forneça a entrada, receba uma saída estruturada e deixe quem chama decidir o que acontece depois. Evite o estado de instância única e as tabelas de funções de chamada de retorno que obriguem quem chama a se tornar o sistema de apoio da biblioteca.
Para funções públicas de retorno e modelos de dados:
- Prefira um único parâmetro de função de chamada de retorno a uma grande tabela de operações.
- Considere mais de cinco funções de chamada de retorno um alerta de reformulação e mais de vinte um erro de projeto da API.
- Documente a propriedade, a vida útil, os valores de retorno e o comportamento em caso de falha das funções de chamada de retorno.
- Não use funções de chamada de retorno sem valor de retorno em operações que possam falhar.
- Prefira registros etiquetados extensíveis a uma enumeração crescente combinada com uma união também crescente.
Tudo o que for instalado como cabeçalho faz parte da API pública, independentemente de seu rótulo. Torne explícitas a propriedade e a vida útil dos buffers, especialmente no caso de armazenamento estático interno.
O código novo não deve introduzir interfaces obsoletas. Para marcar uma interface como obsoleta, não pode haver usuários restantes dentro da árvore, e são necessários documentação de lançamento, um caminho de migração e uma anotação visível ao compilador. Coloque anotações públicas, experimentais e internas exatamente onde a cadeia de ferramentas espera, exporte símbolos a partir das definições no código-fonte e use versionamento de ABI para alterações incompatíveis em assinaturas estáveis. Nunca solicite edições manuais em mapas de símbolos gerados.
## Deixar o estilo mecânico para as ferramentas e revisar o que elas não pegam
Deixe que formatadores, ferramentas de alterações semânticas e scripts de validação do repositório cuidem das substituições mecânicas. Use revisão humana ou por IA nos casos que essas ferramentas não conseguem compreender.
Verifique as regras estabelecidas do projeto para indentação, finais de linha, grupos de inclusões, chaves, organização de funções, identificadores e prefixos de espaços de nomes. Exija prefixos exclusivos em símbolos de bibliotecas ou controladores visíveis externamente para evitar colisões na vinculação estática. Use terminologia inclusiva.
Prefira tipos booleanos reais para estados de verdadeiro ou falso, mas mantenha inteiros para códigos de erro ou valores com vários estados e evite alterações de tipo sem relação com a tarefa em código consolidado. Mantenha constantes as tabelas de despacho de funções em tempo de compilação, a menos que o registro em tempo de execução ou a detecção de capacidades as modifique.
Combine as primitivas de alocação e cópia com o caminho dos dados:
- Use alocação comum no monte para dados gerais de controle.
- Use alocação visível ao dispositivo, ciente de NUMA e inicializada com zeros para DMA, filas ou dados entre processos.
- Use cópia em massa otimizada somente quando o caminho rápido se beneficiar e o contrato correspondente for atendido.
Os comentários devem explicar restrições e intenções, não repetir o código.
## Atualizar testes e documentação junto com cada mudança de código
Cada confirmação de mudanças deve poder ser compilada de forma independente, mas quem analisa apenas uma alteração não deve especular sobre a ordem da série. Valide usando compiladores, alvos, opções e scripts de compilação compatíveis com o projeto.
Adicione testes específicos para novos comportamentos e APIs públicas. Use as asserções de testes funcionais e o executor de conjuntos de testes do repositório, registre com precisão os requisitos do ambiente e forneça pelo menos uma implementação para uma nova API voltada a dispositivos.
Atualize o código e a documentação de forma atômica:
- Documente APIs públicas e mudanças importantes visíveis ao usuário.
- Mantenha matrizes de funcionalidades e a documentação de operações coerentes com a implementação.
- Atualize somente as notas da versão atual para APIs públicas, novos controladores ou mudanças significativas de comportamento.
- Não exija notas de versão para mudanças restritas a testes ou à implementação interna.
- Prefira listas de definições em documentação estruturada quando cada item for um termo acompanhado de uma descrição substancial; mantenha listas simples para itens curtos e procedimentos.
Aplique o formatador da linguagem do sistema de compilação e as regras de ordenação usados pelo repositório. Valide Python com o formatador e a política de comprimento de linha designados.
## Aplicar regras de ramificações estáveis só quando o destino for estável
Use regras estritas de versões estáveis somente quando a ramificação ou versão de destino estiver explicitamente identificada como estável. Nesse caso, permita apenas correções de defeitos: nenhuma nova funcionalidade, API pública, alteração de ABI, símbolo, opção de configuração nem refatoração sem relação com a correção.
Exija que uma retroportação faça referência à correção original e siga a convenção de notificação de versões estáveis do projeto. Considere uma limpeza ampla em torno de uma pequena correção um alerta, pois ela aumenta o risco da retroportação.
Se nenhuma versão for especificada, pressuponha a ramificação principal de desenvolvimento, na qual novas funcionalidades e APIs podem ser válidas. Nunca aplique proibições exclusivas de versões estáveis apenas porque o repositório também mantém ramificações estáveis.
## Dar correções concretas e revisar os achados duas vezes antes de enviar
Classifique como erros os defeitos confirmados de segurança da memória, sincronização, limites, limpeza, criptografia, ABI e compilação. Use alertas para testes ou documentação ausentes, formato inadequado da API, incorporação de elementos obsoletos, uso incorreto da alocação e problemas de manutenção com alta confiança.
Não relate:
- Omissões em mapas gerados, detalhes de direitos autorais ou formatação de confirmações que já sejam responsabilidade das ferramentas de validação.
- Usos corretos de `volatile` em hardware, bloqueios privativos de um processo, recepção em vários segmentos ou macros de teste atuais.
- Pedidos vagos para verificar algo sem evidências de que esteja errado.
- Alterações sem problemas, falhas especulativas entre alterações ou observações sem uma ação corretiva.
Para cada problema real, declare primeiro o problema, explique o impacto somente quando ele não for óbvio e forneça uma correção específica ou uma orientação para o código.
Antes de enviar, faça duas revisões separadas:
1. Revisão de correção: recupere achados plausíveis de correção que foram descartados sem provas e confirme que os caminhos dos recursos, a vida útil, os limites e a propagação de erros foram rastreados.
2. Revisão de falsos positivos: remova todos os itens de estilo ou processo que a própria análise considerou aceitáveis, corretos ou inofensivos.
Uma lista vazia de achados após essas revisões é válida. Não invente comentários para preenchê-la.
