Lo más común en mi experiencia es simplemente ilegible, difícil de mantener el código, bueno, ilegible en un tiempo razonable. Sin comentarios, variables sin sentido y nombres de funciones: recuerdo vívidamente un programa COBOL donde todas las variables fueron elegidas como bromas, por lo que fue “MOVE COW TO BULL”. y así. La falta de comentarios / nombres significativos significa que tienes que resolver lo que el programador estaba intentando: si la función se llama fnParseStringForTokens, tienes una idea bastante buena de lo que va a hacer, mientras que si se llama x31 (y todos los demás son nombres similares) es un poco más difícil.
Aquí hay un buen ejemplo de StackExchange de por qué los comentarios pueden ser importantes:
En algunos casos, ninguna cantidad de buenos nombres, refactorización, etc. puede reemplazar un comentario. Solo mira este ejemplo del mundo real (el idioma es Groovy):
response.contentType = “text / html”
- Edité una pregunta, pero no se hicieron cambios. ¿Es esto un problema técnico?
- Si solo recibo una cirugía de reasignación de género, ¿también necesitaré otros procedimientos?
- Estoy viajando a Sao Paulo en Brasil en un mes y soy de Nairobi, Kenia. ¿Qué debo esperar?
- Estoy buscando comprar un lote arbolado de varios acres. Sin embargo, sigo encontrando lotes que se borran. ¿Por qué limpian los lotes? ¿Hay alguna razón financiera, salud de la tierra o alguna otra razón por la que hacen esto?
- ¿Por qué me matan tan rápido en Cs: Go?
render ‘{“éxito”: verdadero}’
Parece extraño, ¿no? ¿Probablemente un error de copiar-pegar? ¿Llora por una corrección de errores?
Ahora lo mismo con los comentarios:// NO TOQUE LAS SIGUIENTES DOS LÍNEAS; ¡ExtJS UploadForm lo requiere exactamente así! response.contentType = “text / html” // debe ser text / html para que el navegador muestre la respuesta dentro del iframe invisible, donde ExtJS puede acceder a él
render ‘{“success”: true}’ // ExtJS espera eso, de lo contrario llamará al controlador de fallas en lugar del controlador de éxito
(“Los comentarios son un olor a código”)
El siguiente más común y más peligroso es la falta de error y la verificación de límites. Esta es probablemente la causa más común de dolores de cabeza de seguridad y fallas del programa. No se verifican las entradas nulas correctamente, no se verifican las longitudes frente a los tamaños del búfer, los valores de retorno de las funciones y la entrada del usuario. Mire cuántos CVE de seguridad se deben a estos tres y verá lo que quiero decir.
Ejemplo simple en C:
/ * scanf demostración de desbordamiento de búfer
#include
int main ()
{
char str [20];
printf (“Ingrese hasta 20 caracteres:”);
scanf (“% s”, str);
printf (“Ingresaste:% s \ n”, str);
devuelve 0;
}
No se le pide a scanf que verifique la longitud de la cadena o que le ponga una longitud máxima; debe leer scanf (“% 19s”, str) para restringir la longitud a 19 caracteres más el byte nulo. Este código es un candidato de conexión clásico de “desbordamiento de búfer”, ya que ahora puedo sobrescribir casi cualquier parte del segmento de pila por encima de la variable str .
Poner 20 en la longitud es otro error común, el programador olvida que en C tiene un terminador de byte nulo en una cadena … No es tan malo como omitir el número por completo, pero permitiría la corrupción de un byte de pila.
La tercera, y nuevamente muy peligrosa, es la condición de falla o no probada, comúnmente causada por el diseño del lenguaje. Muchos, muchos errores de gran problema se deben a esto. Por ejemplo, un programador puede omitir un caso (comúnmente el caso nulo) en una serie de opciones y permitir la transición a una rutina que no debería alcanzarse. O bien, el programa puede malinterpretar el “azúcar sintáctico” del lenguaje y creer que está en una condición en la que no lo está, o al tratar de ser conciso, el programador introduce un error grave.
Aquí está el error SSL CVE-2014-1266 de Apple:
. . . hashOut.data = hashes + SSL_MD5_DIGEST_LEN;
hashOut.length = SSL_SHA1_DIGEST_LEN;
if ((err = SSLFreeBuffer (& hashCtx))! = 0)
ir a fallar;
if ((err = ReadyHash (& SSLHashSHA1, & hashCtx))! = 0)
ir a fallar;
if ((err = SSLHashSHA1.update (& hashCtx, & clientRandom))! = 0)
ir a fallar;
if ((err = SSLHashSHA1.update (& hashCtx, & serverRandom))! = 0)
ir a fallar;
if ((err = SSLHashSHA1.update (& hashCtx, &ignedParams))! = 0)
ir a fallar;
ir a fallar;
if ((err = SSLHashSHA1.final (& hashCtx, & hashOut))! = 0) goto fail;
err = sslRawVerify (…);
Hay cuatro errores aquí en mi mente:
- La obvia: la última prueba no se llevó a cabo, lo que causó el error de seguridad (el goto repetido hace que el código salte a “fallar” pero con un valor de error que no se establece en este segmento, pero se inicializó a 0 y, por lo tanto, ” No hay error”)
- Si va a llamar a una etiqueta “falla”, entonces debería ser una falla, no “una falla si llego aquí con un error establecido en distinto de cero”.
- No usar el azúcar sintáctico del lenguaje para defenderse. El uso de la sintaxis “if (condition) {..statements …;}”, mientras que el costo de un par de caracteres habría hecho que este error sea un poco más obvio y un poco menos probable de que ocurra; es común en los lenguajes de tipo C ver errores como esta
- Mal diseño: si está probando una condición de error, entonces tener una ruta donde cualquier tipo de caída puede resultar en un pase es malo. Hay muchas formas mejores de diseñar este código: mi preferido habría sido usar el || funciona para cada una de las pruebas y el hecho de que en los lenguajes de tipo C (a! = 0) es idéntico a (a), pero otros tendrán mejores ideas (¡no probado en el Objetivo C porque no lo uso!):
err = SSLFreeBuffer (& hashCtx)) ||
ReadyHash (& SSLHashSHA1, & hashCtx)) ||
SSLHashSHA1.update (& hashCtx, & clientRandom)) ||
SSLHashSHA1.update (& hashCtx, & serverRandom)) ||
SSLHashSHA1.update (& hashCtx, &ignedParams)) ||
SSLHashSHA1.final (& hashCtx, & hashOut)) ||
sslRawVerify (…);
// Hemos hecho todas las pruebas, ahora mira si hemos fallado
si (err) {
// acción fallida
}
más {
// acción de éxito
}
Es más fácil de entender hacia dónde vamos y evita la necesidad de los múltiples problemas …