Debian Jessie: ¿cómo va el "freeze"? (2)

Llevamos justo un mes de freeze de Debian "Jessie" y la cosa va tomando forma. No es que todavía no queden muchos bugs RC (ahora mismo 243 según el BTS y 227 según UDD), pero al menos la cuenta va hacia abajo, no como hace 15 días que crecía.

De momento la previsión de Lucas Nussbaum de 12 semanas, cuando ya han transcurrido 4, entra dentro de lo posible, máxime teniendo en cuenta que algunos de esos bugs no habría que incluirlos en la cuenta. Por ejemplo, los bugs de seguridad son corregidos incluso después de ser lanzada la estable, así que realmente no son bloqueantes para el lanzamiento (aunque obviamente no creo que nadie pensara en lanzar la versión estable con bugs de seguridad flagrantes conocidos). Para otros bugs ya existe la corrección pertinente, incluso ya está subida a unstable, pero ésta no ha pasado todavía a testing.

Por eso las estadísticas que realiza semanalmente Richard Hartmann desglosan los bugs en varias categorías, tratando de captar el número real de bugs que quedan por solucionar (distinto del número de bugs que están en fase de figurar como solucionados). Estas cifras son más pequeñas (en algún caso mucho más pequeñas), aunque no hay que lanzar las campanas al vuelo porque se siguen encontrándo bugs constantemente. Lo importante es la tendencia: que el número de bugs encontrados sea paulatinamente menor hasta que éstos converjan a cero. A ser posible en un número no infinito de incrementos... :-)

Teniendo más de 30.000 paquetes, es evidente que la mayoría de los bugs (por simple cuestión de números) no están dentro del subconjunto de paquetes que tenemos instalado. Así que la capacidad de contribuir a verificar o solucionar bugs está limitada a unos pocos de toda la lista. Así que captó mi atención el ver un bug en un programa que uso diariamente: mutt. El bug en cuestión era el #771125. Lo abro y en el segundo mensaje me encuentro esto:

char *mutt_substrdup (const char *begin, const char *end)
{
  size_t len;
  char *p;

  if (end)
    len = end - begin;
  else
    len = strlen (begin);

  p = safe_malloc (len + 1);
  memcpy (p, begin, len);
  p[len] = 0;
  return p;
}

Si conocéis C, ahora mismo os estaréis echando las manos a la cabeza como yo me las eché al ver eso. No hace falta ni seguir leyendo el resto de intercambios del bug para saber dónde está el potencial problema. ¿Lo habéis visto? Sí, seguro que sí.

Es de suponer por el nombre y el cuerpo que esta función realiza una copia (supuestamente segura) de una cadena de texto. Dicha cadena de texto, seguramente para evitarse problemas con caracteres \0, acepta un puntero al fin de la cadena a copiar aparte de un puntero al inicio, ¡pero en ningún momento se comprueba que el puntero apuntando al final es posterior al que apunta al inicio!

Dicho sea de paso, tampoco se comprueba que el puntero begin no sea nulo, lo que en mi opinión es un segundo bug esperando al acecho una oportunidad de liarla parda.

El bug no está únicamente en la función, está también en el código que la invoca. Pero es una ley de la programación defensiva que cada función se proteja de usos indebidos, de forma que si hay un bug en el codigo que la llama éste no se propague más allá.

Por ejemplo, en este caso, hay un invariante que se debe cumplir siempre: begin != NULL. Y hay un invariante que debe cumplirse siempre que se suministra el puntero end: begin <= end. Y fijáos que he puesto "menor o igual" y no "menor" para que se trate también el caso de copiar la cadena vacía, que puede tener sentido si se quiere reducir el número de casos especiales a tratar en los algoritmos que llamen a esta función.

De hecho, el caso en el que no se suministra el puntero end y se se emplea strlen() para calcular el tamaño de la cadena a duplicar no maneja correctamente cadenas con carácteres \0, lo cual puede ser un problema dependiendo de las asunciones que haga el código llamante.

Yo desde luego dormiría más tranquilo con una función con una aserción:

assert( begin != NULL && end != NULL &&  begin <= end );
len = end - begin;

que la protegiera de todo mal1.

Si esto está así, sinceramente no quiero ni pensar cómo está el resto del código de mutt.

:wq


  1. O de casi todo mal, ya que si end - begin es mayor que el máximo almacenable en un size_t podríamos tener problemas. 

blogroll

social