Partilhar via


Descritores de correlação

Um descritor de correlação é uma cadeia de caracteres de formato que descreve uma expressão baseada em um argumento relacionado a outro argumento. Um descritor de correlação é necessário para lidar com semânticas relacionadas a atributos como [size_is()], [length_is()], [switch_is()] e [iid_is()]. Os descritores de correlação são usados com matrizes, ponteiros de tamanho, uniões e ponteiros de interface. O valor da expressão eventual pode ser um tamanho, um comprimento, um discriminante de união ou um ponteiro para uma IID, respectivamente. Em termos de cadeias de caracteres de formato, os descritores de correlação são usados com matrizes, uniões e ponteiros de interface. Um ponteiro de tamanho é descrito em cadeias de caracteres de formato como um ponteiro para uma matriz.

Há duas rotinas executando cálculos básicos de expressão: NdrpComputeConformance é usado para tamanhos, switches e IID* enquanto NdrpComputeVariance é usado para comprimentos. Há também uma única rotina para executar uma validação de valor de correlação para a funcionalidade de negação de ataque.

Os descritores de correlação foram concebidos para suportar apenas expressões muito limitadas. Para situações complicadas, o compilador gera uma rotina de avaliação de expressão para ser chamada pelo mecanismo quando necessário.

Um descritor de correlação tem o seguinte formato:

correlation_type<1>
correlation_operator<1>
offset<2>
[robust_flags<2>]

O descritor de correlação correlation_type<1> consiste em dois nibbles: os 4 bits superiores descrevem onde a expressão pode ser encontrada e os 4 bits inferiores descrevem o tipo do valor da expressão.

O nibble superior pode ter um destes cinco valores:

00  FC_NORMAL_CONFORMANCE
10  FC_POINTER_CONFORMANCE
20  FC_TOP_LEVEL_CONFORMANCE
80  FC_TOP_LEVEL_MULTID_CONFORMANCE
40  FC_CONSTANT_CONFORMANCE

FC_NORMAL_CONFORMANCE

Um caso normal de conformidade, como o descrito num campo de uma estrutura.

FC_POINTER_CONFORMANCE

Para ponteiros atribuídos (size_is(), length_is()) que são campos em uma estrutura. Isso afeta a maneira como o ponteiro de memória base é definido.

FC_TOP_LEVEL_CONFORMANCE

Para conformidade de nível superior descrita por outro parâmetro.

FC_TOP_LEVEL_MULTID_CONFORMANCE

Para conformidade de nível superior de uma matriz multidimensional descrita por outro parâmetro.

Observação

Matrizes e ponteiros de tamanho multidimensional acionam um switch para –Oicf.

 

FC_CONSTANT_CONFORMANCE

Para um valor constante. O compilador pré-calcula o valor a partir de uma expressão constante fornecida pelo usuário. Quando este é o caso, os 3 bytes subsequentes na descrição de conformidade contêm os 3 bytes inferiores de um longo descrevendo o tamanho da conformidade. Não é necessário nenhum cálculo adicional.

O nibble inferior dá o tipo do valor que precisa ser extraído da memória:

FC_LONG | FC_ULONG | 
FC_SHORT | FC_USHORT | 
FC_SMALL | FC_USMALL | 
FC_HYPER

Observação

Não há suporte para expressões de 64 bits. FC_HYPER é usado apenas para iid_is() em plataformas de 64 bits para extrair o valor do ponteiro para IID*.

O compilador define o tipo nibble como zero para os seguintes casos: expressão constante mencionada acima e quando a rotina de expressão de avaliação precisa ser chamada, por exemplo, quando FC_CONSTANT_CONFORMANCE e FC_CALLBACK são usados.

 

O campo> size_is_op<1 permite aplicar uma das seguintes operações à variável de conformidade:

FC_DEREFERENCE | 
FC_DIV_2 | FC_MULT_2 | FC_SUB_1 | FC_ADD_1 | 
FC_CALLBACK

A constante FC_DEREFERENCE é usada para correlação sendo um pointee, como para [size_is(*pL)]. Os operadores aritméticos apenas usam a constante indicada. A constante FC_CALLBACK indica que uma rotina de avaliação de expressão precisa ser chamada.

O deslocamento<campo de 2> é tipicamente um deslocamento de memória relativa para a variável de argumento de expressão. Também pode ser um índice de avaliação de expressão – rotina. Como mencionado anteriormente neste documento, para expressões constantes é uma parte do valor real e final da expressão.

A interpretação do campo de deslocamento<2> como deslocamento de memória depende da complexidade da expressão, da localização da variável de expressão e, no caso de uma matriz, se a matriz é realmente um ponteiro atribuído.

Se a matriz é um ponteiro atribuído e a variável de conformidade é um campo em uma estrutura, o campo de deslocamento contém o deslocamento do início da estrutura para o campo que descreve a conformidade. Se a matriz não for um ponteiro atribuído e a variável de conformidade for um campo em uma estrutura, o campo de deslocamento conterá o deslocamento do final da parte não conforme da estrutura para o campo que descreve a conformidade. Normalmente, a matriz conforme está no final da estrutura.

Para conformidade de nível superior, o campo offset contém o deslocamento da localização do primeiro parâmetro do stub na pilha para o parâmetro que descreve a conformidade. Isso não é usado no modo de –OS. Existem outras exceções à interpretação do campo de compensação; Essas exceções são descritas na descrição desses tipos.

Quando o deslocamento<2> é usado com FC_CALLBACK, ele contém um índice na tabela de rotina de avaliação de expressão gerada pelo compilador. A mensagem de stub é passada para a rotina de avaliação, que então calcula o valor de conformidade e o atribui ao campo MaxCount da mensagem de stub.

O campo> robust_flags<2 foi adicionado para o Windows 2000 para suportar /robust, como o recurso de negação de ataques. Os seguintes sinalizadores são definidos no primeiro byte:

typedef  struct  _NDR_CORRELATION_FLAGS
  {
  unsigned char   Early     : 1;
  unsigned char   Split     : 1;
  unsigned char   IsIidIs   : 1;
  unsigned char   DontCheck : 1;
  unsigned char   Unused    : 4;
  } NDR_CORRELATION_FLAGS;

O sinalizador Early indica correlação precoce versus tardia. Uma correlação inicial é quando o argumento de expressão precede o argumento descrito, por exemplo, um argumento de tamanho está antes de um argumento de ponteiro de tamanho. Uma correlação tardia é quando o argumento da expressão vem depois do argumento relacionado. O mecanismo executa a validação dos valores de correlação iniciais imediatamente, os valores de correlação tardia são armazenados para verificação após o desempacotamento ser feito.

O sinalizador Split indica uma divisão assíncrona entre os argumentos [in] e [out]. Por exemplo, um argumento size pode ser [in] enquanto o ponteiro size pode estar [out]. No contexto assíncrono DCOM, esses argumentos estão em pilhas diferentes, então o mecanismo deve estar ciente disso.

O sinalizador IsIidIs indica uma correlação iid_is(). A rotina NdrComputeConformance é enganada para obter um ponteiro para IID como um valor de expressão, mas a rotina de validação não pode comparar esses valores (eles seriam ponteiros) e, portanto, o sinalizador indica que IIDs reais precisam ser comparados.

Descrição da variância e outros atributos da matriz

O formato do campo de descrição da variância é idêntico ao campo de descrição da conformidade. A diferença é que um campo de mensagem de stub diferente é usado pelo mecanismo de notificação de falha na entrega como uma variável temporária. No caso da descrição da variância, é o comprimento que é avaliado e o campo correspondente é chamado ActualLength.

Com variância, o desvio de arranque é normalmente zero e o motor é ajustado em conformidade. Se o atributo first_is() for aplicado a uma matriz variável conforme, um retorno de chamada para uma rotina de avaliação de expressão será forçado.