Descriptores de correlación
Un descriptor de correlación es una cadena de formato que describe una expresión basada en un argumento relacionado con otro argumento. Se necesita un descriptor de correlación para controlar la semántica relacionada con atributos como [size_is()], [length_is()], [switch_is()] y [iid_is()]. Los descriptores de correlación se usan con matrices, punteros de tamaño, uniones e punteros de interfaz. El valor de expresión final puede ser un tamaño, una longitud, un discriminante de unión o un puntero a un IID, respectivamente. En términos de cadenas de formato, los descriptores de correlación se usan con matrices, uniones e punteros de interfaz. Un puntero de tamaño se describe en cadenas de formato como puntero a una matriz.
Hay dos rutinas que realizan cálculos de expresiones básicas: NdrpComputeConformance se usa para tamaños, modificadores e IID*, mientras que NdrpComputeVariance se usa para longitudes. También hay una sola rutina para realizar una validación de valores de correlación para la funcionalidad de denegación de ataque.
Los descriptores de correlación se han diseñado para admitir expresiones muy limitadas. En situaciones complicadas, el compilador genera una rutina de evaluación de expresiones a la que llamará el motor cuando sea necesario.
Un descriptor de correlación tiene el formato siguiente:
correlation_type<1>
correlation_operator<1>
offset<2>
[robust_flags<2>]
El descriptor de correlación correlation_type<1> consta de dos nibbles: los 4 bits superiores describen dónde se puede encontrar la expresión y los 4 bits inferiores describen el tipo del valor de la expresión.
El nibble superior puede tener uno de estos 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
-
Un caso normal de conformidad, como el descrito en un campo de una estructura.
-
FC_POINTER_CONFORMANCE
-
Para punteros con atributos (size_is(),length_is()) que son campos de una estructura. Esto afecta a la forma en que se establece el puntero de memoria base.
-
FC_TOP_LEVEL_CONFORMANCE
-
Para la conformidad de nivel superior descrita por otro parámetro.
-
FC_TOP_LEVEL_MULTID_CONFORMANCE
-
Para la conformidad de nivel superior de una matriz multidimensional descrita por otro parámetro.
Nota
Las matrices y punteros de tamaño multidimensional desencadenan un modificador a –Oicf.
-
FC_CONSTANT_CONFORMANCE
-
Para un valor constante. El compilador precalcula el valor de una expresión constante proporcionada por el usuario. Cuando este es el caso, los 3 bytes posteriores de la descripción de conformidad contienen los 3 bytes inferiores de un largo que describe el tamaño de conformidad. No se requiere ningún cálculo adicional.
El nibble inferior proporciona el tipo del valor que se debe extraer de la memoria:
FC_LONG | FC_ULONG |
FC_SHORT | FC_USHORT |
FC_SMALL | FC_USMALL |
FC_HYPER
Nota
No se admiten expresiones de 64 bits. FC_HYPER solo se usa para iid_is() en plataformas de 64 bits para extraer el valor de puntero para IID*.
El compilador establece el tipo nibble en cero para los casos siguientes: expresión constante mencionada anteriormente y cuando se debe llamar a la rutina de expresión de evaluación, por ejemplo, cuando se usan FC_CONSTANT_CONFORMANCE y FC_CALLBACK.
El campo size_is_op<1> permite aplicar una de las siguientes operaciones a la variable de conformidad:
FC_DEREFERENCE |
FC_DIV_2 | FC_MULT_2 | FC_SUB_1 | FC_ADD_1 |
FC_CALLBACK
La constante FC_DEREFERENCE se usa para que la correlación sea un puntero, como para [size_is(*pL)].. Los operadores aritméticos simplemente usan la constante indicada. La constante FC_CALLBACK indica que se debe llamar a una rutina de evaluación de expresiones.
El campo offset<2> suele ser un desplazamiento de memoria relativo a la variable de argumento de expresión. También puede ser un índice de evaluación y rutina de expresión. Como se mencionó anteriormente en este documento, para las expresiones constantes forma parte del valor de expresión final real.
La interpretación del campo offset<2> como desplazamiento de memoria depende de la complejidad de la expresión, la ubicación de la variable de expresión y, en el caso de una matriz, si la matriz es realmente un puntero con atributos.
Si la matriz es un puntero con atributos y la variable de conformidad es un campo de una estructura, el campo de desplazamiento contiene el desplazamiento desde el principio de la estructura hasta el campo de descripción de conformidad. Si la matriz no es un puntero con atributos y la variable de conformidad es un campo de una estructura, el campo de desplazamiento contiene el desplazamiento desde el final de la parte no conforme de la estructura al campo de descripción de conformidad. Normalmente, la matriz conforme está al final de la estructura.
Para la conformidad de nivel superior, el campo offset contiene el desplazamiento de la ubicación del primer parámetro del código auxiliar en la pila al parámetro que describe la conformidad. Esto no se usa en el modo –Os . Hay otras excepciones a la interpretación del campo de desplazamiento; estas excepciones se describen en la descripción de esos tipos.
Cuando se usa el desplazamiento<2> con FC_CALLBACK, contiene un índice en la tabla de rutina de evaluación de expresiones generada por el compilador. El mensaje de código auxiliar se pasa a la rutina de evaluación, que, a continuación, calcula el valor de conformidad y lo asigna al campo MaxCount del mensaje de código auxiliar.
El campo robust_flags<2> se ha agregado para Windows 2000 para admitir /robust, como la característica de denegación de ataques. Las marcas siguientes se definen en el primer 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;
La marca Early indica una correlación temprana frente a una correlación tardía. Una correlación temprana es cuando el argumento expression precede al argumento descrito, por ejemplo, un argumento size es antes de un argumento de puntero de tamaño. Una correlación tardía es cuando el argumento de expresión viene después del argumento relacionado. El motor realiza la validación de los valores de correlación tempranos inmediatamente, los valores de correlación en tiempo de ejecución se almacenan para comprobar después de que se realice la desmarshación.
La marca Split indica una división asincrónica entre los argumentos [in] y [out]. Por ejemplo, un argumento size puede ser [in] mientras que el puntero de tamaño puede ser [out]. En el contexto asincrónico de DCOM, estos argumentos se producen en diferentes pilas, por lo que el motor debe ser consciente de esto.
La marca IsIidIs indica una correlación iid_is(). La rutina NdrComputeConformance se engaña para obtener un puntero a IID como un valor de expresión, pero la rutina de validación no puede comparar dichos valores (serían punteros) y, por tanto, la marca indica que se deben comparar los IID reales.
Descripción de varianza y otros atributos de matriz
El formato del campo de descripción de varianza es idéntico al campo de descripción de conformidad. La diferencia es que el motor de NDR usa un campo de mensaje de código auxiliar diferente como una variable temporal. En el caso de la descripción de la varianza, es la longitud que se evalúa y el campo correspondiente se denomina ActualLength.
Con varianza, el desplazamiento inicial suele ser cero y el motor se ajusta en consecuencia. Si el atributo first_is() se aplica a una matriz variable conforme, se fuerza una devolución de llamada a una rutina de evaluación de expresiones.