Un invariante semántico es una propiedad que debe mantenerse durante la ejecución de un programa para que sus datos y operaciones conserven el significado previsto. En C, estas relaciones suelen existir únicamente como obligaciones informales del programador, porque los tipos estándar no representan conceptos como la capacidad de un búfer, la propiedad de un objeto, la vida útil de un puntero o los límites de una región de memoria.
El texto utiliza como ejemplo la relación entre una longitud, un puntero y la memoria disponible. En una operación como memcpy(p, source, length), la ejecución solo es segura si la longitud no supera la extensión accesible desde p. Si esa proposición se incumple, el fallo puede atribuirse erróneamente a la llamada concreta a memcpy, cuando la ruptura ocurrió antes, durante el cálculo de un tamaño o de un desplazamiento.
La explicación permite unificar vulneraciones distintas, como desbordamiento de enteros, acceso fuera de límites, uso después de liberar y doble liberación. Todas pueden interpretarse como manifestaciones de una misma cadena de invariantes: una cantidad determina un tamaño, el tamaño determina una asignación, el puntero conserva la identidad del objeto, el desplazamiento permanece dentro de la región y la longitud de la copia no excede su extensión restante.
Los casos citados muestran cómo un error aritmético se propaga hasta producir corrupción de memoria. En radire2, CVE-2019-19590 combinó un desbordamiento de entero con un uso después de liberar; en Keccak XKCP, CVE-2022-37454 derivó en un desbordamiento de búfer. Heartbleed, CVE-2014-0160, ilustra una sobrelectura causada por asumir una extensión de memoria mayor que la realmente disponible. El texto concluye que el diseño de lenguajes con seguridad de memoria debería incorporar estas relaciones semánticas en sus tipos o mecanismos de comprobación.
