2009-05-18 19 views
10

Como algunos de ustedes deben saber, Microsoft banned memcpy() from their Security Development Lifecycle, reemplazándolo con memcpy_s().Microsoft SDL y memcpy deprecation

void *memcpy(void *dest, const void *src, size_t n); 

/* simplified signature */ 
errno_t memcpy_s(void *dst, size_t dstsize, const void *src, size_t n); 

Así que si su código solía ser:

if (in_len > dst_len) { 
    /* error */ 
} 
memcpy(dst, src, in_len); 

se convierte en:

if (memcpy_s(dst, dst_len, src, src_len)) { 
    /* error */ 
} 

O, con truncamiento,

memcpy(dst, src, min(in_len, dst_len)); 

vs

(void)memcpy_s(dst, dst_len, src, src_len); 

La pregunta: ¿cómo un parámetro de longitud adicional hace que el código sea más seguro? Para usar memcpy(), ya debería tener los cuatro parámetros conocidos y pasar la longitud apropiada como tercer argumento. ¿Qué me impide cometer el mismo error al calcular mal el tamaño del búfer de destino y pasar el valo equivocado de dst_size? No veo por qué es diferente de memcpy() y por qué está en desuso. ¿Hay algún caso de uso común que no pueda ver? ¿Qué me falta aquí?

+0

Tenga en cuenta que memcpy_s() es parte de C11 Anexo K, que sólo es una * opcional * parte de C11 la especificación. Varios implementadores de compiladores han rechazado el Anexo K y nunca lo implementarán. Por lo tanto, solo úselo si '__STDC_LIB_EXT1__' está definido. Redhat ha recomendado que se elimine de futuras especificaciones C. – DavidJ

Respuesta

14

Nada le impide obtener los parámetros incorrectos en la versión "segura" tampoco. Microsoft parece pensar que siempre usará algo como:

errno_t e = memcpy_s (&dstbuff, sizeof(dstbuff), &srcbuff, sizeof(srcbuff)); 

y verifique el error.

Pero esto solo ayuda a las personas que no saben lo que hacen con el idioma. En mi opinión, ese grupo de personas no debería usar el idioma o deberían aprender cómo funciona correctamente.

Este tipo de muleta no les hace ningún favor a largo plazo ya que su código no será portátil.

Ahora bien, es posible que Microsoft haya realizado algunos análisis y descubrió que había muchos problemas causados ​​por el uso indebido de las personas memcpy() y pensaban que esto lo solucionaría. Pero, si ese fuera el caso, sospecho que una mejor solución sería educar a los desarrolladores en lugar de forzarlos a utilizar funciones no estándar que no estarán disponibles en los compiladores estándar.

+3

"Este tipo de muleta no les hace ningún favor a la larga ..." totalmente de acuerdo, Pax. – ninesided

+3

Primera parte correcta, segunda parte incorrecta: no es una muleta, y en realidad está destinada a aquellos que piensan que son expertos en "cómo funciona el lenguaje", y siempre están buscando atajos. La nueva versión "segura", como dijo @ninesided, te hace pensar en lo que estás haciendo y (con suerte) dejar de tratar de trabajar el idioma. – AviD

+0

Pero debo enfatizar que lo que dices sobre el patrón general que se basa en el uso de sizeof (buf) es un punto excelente, y debe alentarse (a menos que, por supuesto, no estés copiando desde el principio del búfer ... .) – AviD

4

Usted no está perdiendo nada, creo que este fragmento del artículo que vincula a más o menos lo cubre:

Si nada más, te hace memcpy_s pensar en el tamaño de la memoria intermedia de destino .

6

Tiene toda la razón. Si realiza un seguimiento de las longitudes de ambos búferes, memcpy es seguro de usar. Si no lo eres, memcpy_s no te salvará.

1

De acuerdo con Microsoft, esto hará que sea un poco más fácil escribir comprobaciones de calidad de código; puede verificar para asegurarse de que el programador no pasa el mismo valor a ambos parámetros de tamaño (que muchas personas probablemente seguirían teniendo) de la pereza).La otra cosa (que en realidad no está relacionada con la seguridad del código) es que puedes limpiar tu código un poco usando este método, porque hay menos verificaciones que hacer en tu código: la función memcpy_s comprobará que hay espacio suficiente en el búfer de destino, eliminando uno de sus cheques.

Lo más importante de todo es que memcpy_s devuelve un código de error que indica si la copia completa fue exitosa, pero con memcpy no hay forma de estar seguro de esto. Este es lo que Microsoft siente que hace que memcpy_s sea más seguro que memcpy.

+0

Creo que confiar en memcpy_s para hacer verificaciones lógicas ordinarias es una mala práctica, y creo que incluso aquellos que abogan por la función estarían de acuerdo. –

+0

Estoy de acuerdo, esa línea de razonamiento no es mía, sino de Microsoft. He actualizado mi comentario para aclararlo un poco. La segunda parte es mi opinión, pero no creo que la claridad del código sea una gran razón para prohibir esta función. –

8

La duplicación de información siempre es un mal diseño, simplemente te da más oportunidades de obtener algo mal. Microsoft tiene un historial impresionante en lo que respecta al diseño de API, y se ha salvado en el pasado solo por la excelencia de su documentación. Lo más reconfortante es que no pueden eliminar la función memcpy original() - es parte de ANSI C.

+1

+1 Acepto. Creo que el principal problema de seguridad que MS y otros programadores de bajo nivel "hardcore" deberían tratar es el exceso de memoria intermedia. Todo lo demás se puede (debería) verificarse mediante los lenguajes fuertes tipados (C#, Java, Ada, etc.). – ATorras

+1

"no pueden eliminar la función memcpy() original", pero lo que sí pueden hacer es hacer que escupe advertencias. Y si lo desean, pueden hacer que esas advertencias sean difíciles o imposibles de ignorar. –

-1

En realidad, a veces, no nos quedan muchos programadores reales en el mundo que ven el máquina para lo que es y amor cambiando bits alrededor. Un poco fuera del tema lo sé, pero me gusta saber exactamente lo que está pasando y definitivamente no quiero que ningún colector de basura del cojo vaya por el fondo tratando desesperadamente de resolver montones sucios de programadores descuidados. Quiero decir, ¿qué tan difícil es hacer coincidir llamadas a free() con llamadas a malloc()/strdup(), qué tan difícil es asegurarse de que haya asignado suficiente espacio en el búfer para saber que puede llamar a memcpy() saefly? Respuesta: No mucho, pero el 99.9% de los programadores realmente no se preocupan por lo que están haciendo porque simplemente lo hacen por el dinero, no por la pasión de escribir una pieza de código hermosamente brillante.

End Rant.

0

C al igual que el montaje es para las personas que saben lo que están haciendo, recuerdo leer algo así direcly de K & R