Autopsia al código fuente del Zune revela orden de suicidio

(c) Pastie.org

(c) Pastie.org

Para los más fanáticos o para aquellos que requieren de una explicación lógica ante un problema complejo, ya está disponible el código de programación que hizo que miles de reproductores Zune dejaran de funcionar colectivamente. El error comienza en la línea 249.

En circunstancias normales, esto funciona muy bien. La función sigue restando ya sea 365 o 366 hasta que se reduce a menos de un año para luego convertirse en el mes y el día de mes.

Lo que pasa es que en el caso del último día de un año bisiesto, continúa hasta que llega a 366. Debido al if (days>366) la ejecución para de sustraer si el bucle (loop) pasa a ser un año bisiesto. Pero 366 es demasiado grande para salir del bucle principal, lo que se traduce en que el Zune continue en el loop infinito sin hacer nada.

Si el error no se arregla, lo mismo va a suceder el 31 de diciembre del 2012… Microsoft, tienes 3 años… ¿alcanzarás?

Link: PQOAL Real-time clock (RTC) routines for the MC13783 PMIC RTC (Pastie.org)

Compartir Compartir
Publicado por Alexander Schek el 2 de January 2009 en la categoría Destacados, Software con los tags , , , , . Tiene 101 comentarios.

101 Comentarios

Autopsia al código fuente del Zune revela orden de suicidio

Deja tu Comentario ↓
Autopsia al código fuente del Zune revela orden de suicidio

DesaprobarAprobar0Autopsia al código fuente del Zune revela orden de suicidio dijo el 2-1-2009 a las 20:46:

31

[...] Autopsia al código fuente del Zune revela orden de suicidiowww.fayerwayer.com/2009/01/autopsia-al-codigo-fuente-de-zune… por Disacido hace pocos segundos [...]

luis

DesaprobarAprobar1luis dijo el 2-1-2009 a las 20:51:

32

@jrrb

2009 no es bisiesto, 2008 si lo fué

lolcito

DesaprobarAprobar1lolcito dijo el 2-1-2009 a las 20:51:

33

parece ke el aweonao ke escribio eso no hizo el ejercicio del if y el año bisiesto ke te enseñan en todos lados para explicar estructuras de control xD

NC

DesaprobarAprobar5NC dijo el 2-1-2009 a las 20:58:

34

Eso es puro y simple C.

Regalamos Ipod

DesaprobarAprobar-2Regalamos Ipod dijo el 2-1-2009 a las 21:02:

35

ajajajaja xD… muy simples simples con sus ifs :S

creo que tiene bien merecido que los boten xD..

microsoft tiene la culpa de contrarar a gnte asi :S y no buscar calidad antes de cantidad

farve

DesaprobarAprobar0farve dijo el 2-1-2009 a las 21:12:

36

son 4 años no 3!

Luis Vera

DesaprobarAprobar32Luis Vera dijo el 2-1-2009 a las 21:15:

37

q ironía…. Microsoft tiene un problema con Infinite Loop

freak!

DesaprobarAprobar0freak! dijo el 2-1-2009 a las 21:23:

38

vayance acostumbrando porque Microsoft no lo soluciona dentro de dies años…

Carlos

DesaprobarAprobar-1Carlos dijo el 2-1-2009 a las 21:25:

39

omg ese error lo comete uno en primer año no mas xD n000000000bz
bueno suele pasar.
Ojala microsoft pueda actualizar sus Zune para que el error sea solucionado

victor

DesaprobarAprobar7victor dijo el 2-1-2009 a las 21:54:

40

no es por causar molestias, ¿pero de donde salio ese pedazo de codigo fuente?, al que todos sabemos microsoft se niega a mostrar rotundamente :S

el_dva,

DesaprobarAprobar1el_dva, dijo el 2-1-2009 a las 21:56:

41

Exacto el error esta en la linea 263 deberia ser if (days>365), como no detectaron ese error con las pruebas unitarias!

Andres

DesaprobarAprobar1Andres dijo el 2-1-2009 a las 22:12:

42

Para un año bisiesto el día 366 es el 31 de diciembre, mientras que para un año normal sería el 01 de enero del siguiente año. El problema lo presenta el while (days > 365), porque para un año normal 366 sería el 01 de enero, pero como este año fue bisiesto el while deberia ser while (days > 366) para que este código funcione.

Al final cuando es el 31 de diciembre del 2008 osea days es 366 cumple la condición IsLeapYear(year) año bisiesto, pero no la condición if (days > 366) lo cual es correcto porque todavia no es el 01 de enero.

Para mi al final el error lo tiene la condición del loop while.

mrjavo

DesaprobarAprobar2mrjavo dijo el 2-1-2009 a las 22:23:

43

Debe ser puro y simple C… pq si no no veriamos semejante manejo tan arcaico de las fechas siendo q hoy en dia hay ya tipos DATE mas sencillos de manejar, java los tiene :D , C# y VB.Net tambien, pero me imagino q igual no es posible por ser una pieza de HW q tiene q manejar lenguajes lo mas cercanos al bajo nivel

Ricardo

DesaprobarAprobar0Ricardo dijo el 2-1-2009 a las 22:37:

44

Increíble que el problema sea un simple “=” y más que la gente de MS digan que se vuelva a prender el Zune y setear la fecha a 1 de enero de 2009. ¿Llegarán a corregir el error? Todos lo usuarios de Zune esperan eso.

Saludos!

reinaldo

DesaprobarAprobar1reinaldo dijo el 2-1-2009 a las 22:46:

45

concluyendo parece que un signo “=” fue el que falto.

desgraciadamente nada se, la verdad es que no entendi nada a los programadores que vistan FW, pero si el error es ese pequeño signo hay una razon mas para preferir software libre u open source (como quieran llamarle) a la semana un programador habria pillado el error, hecho la correccion y avisado a la gente para descargar una actualizacion.

por eso prefiero los mp4 de menos de 60 lucas, nunca me han dado problemas.

hashing

DesaprobarAprobar-3hashing dijo el 2-1-2009 a las 22:53:

46

Tendría que ver el resto del código, pero ese no es necesariamente el problema. Están PROFUNDAMENTE equivocados.

dpc

DesaprobarAprobar1dpc dijo el 2-1-2009 a las 23:47:

47

Basicamente que cuando el zune muestre la hora y la fecha un 31 de diciembre de un año bisiesto, tendra que ir a este procedimiento para calcularlo, y de aqui no saldra nunca, con lo cual dejara de responder.

dpc

DesaprobarAprobar2dpc dijo el 2-1-2009 a las 23:50:

48

hashing no digas bobadas, ese es el error, quieres ver el codigo completo?
aqui esta:

BOOL ConvertDays(UINT32 days, SYSTEMTIME* lpTime)
{
int dayofweek, month, year;
UINT8 *month_tab;

//Calculate current day of the week
dayofweek = GetDayOfWeek(days);

year = ORIGINYEAR;

while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}

// Determine whether it is a leap year
month_tab = (UINT8 *)((IsLeapYear(year))? monthtable_leap : monthtable);

for (month=0; month<12; month++)
{
if (days wDay = days;
lpTime->wDayOfWeek = dayofweek;
lpTime->wMonth = month;
lpTime->wYear = year;

return TRUE;
}

de http://pastie.org/349916

Alphamania

DesaprobarAprobar2Alphamania dijo el 2-1-2009 a las 23:51:

49

K complicaa la computacion :S… x un error minimo queda LA – KA – GA

Guillermo

DesaprobarAprobar6Guillermo dijo el 2-1-2009 a las 23:54:

50

Habria k ver el resto del codigo, pero no es tan facil como agragar un signo =, ya k asi dejarian el contador de dias en el dia cero y estaria = de malo el codigo, fijence que para que entre en el while debe estar en el dia 366 y si el año no es bisiesto deja el contador de dias en 1 y le suma un año al contador d años, pero cndo es bisiesto la idea es que pase al dia 367 para restarle 366 y dejar el contador d dias en 1, pero como la funcion k cuenta los dias esta fuera del while no alcanza a aumentar a 367 y queda en un loop infinito.

No se si m explique bien y no creo =P pero hice lo que pude, solo k estan equivocados los que dicen que poniendole un = se arreglaria el error ya que no es tan simple como eso.

Gon

DesaprobarAprobar4Gon dijo el 3-1-2009 a las 00:01:

51

Bueh, la verdad es que no me he fijado completamente en todos los casos, pero igualmente me cabe otra duda. EXISTEN librerías para contar fechas y horas, entonces ¿porque reescribir esa porción de código?

Dicen que el mejor programador no es quien hace los mejores algoritmos, ni los que optimizan, ni los que podrían reprogramarlo todo desde cero. El mejor programador es el que sabe aprovechar y reutilizar lo que tiene a mano.

TurboMAC

DesaprobarAprobar-1TurboMAC dijo el 3-1-2009 a las 00:02:

52

En que esta programado Zune??? En C??? En visual???

hashing

DesaprobarAprobar0hashing dijo el 3-1-2009 a las 00:17:

53

@dpc,
ok, viendo el código completo (de hecho, las siguientes dos líneas) si, el error es evidente. Pero hasta el punto que se presenta en el artículo, es insuficiente. El error fácilmente se habría podido corregir con una línea antes de cerrar el ciclo. Si leiste mi post, decía que eso no es NECESARIAMENTE el problema. Claro, viendo tu post (y, mejor, el link) si aparece el error, pero recién ahí.
Lo más fácil y presentable, de hecho, era prescindir de un par de líneas antes. Era mejor código y error-free.

@Guillermo,
Creo que no lo captaste del todo. Sigue el código considerando los siguientes tips:
-A esta función, le ingresas la cantidad de días desde el 1 de enero del “año de origen” (1980).
-restas de 366/365 días (año bisiesto/normal) a la vez que sumas un año. Te quedas, al finalizar el while, con el índice de día (número) del año en curso. Como al ir restando la cantidad de días del año, además incrementas la variable year, también tienes el año (recuerda, vas incrementando desde 1980).
-Para obtener el mes y el día del mes opera parecido, considerando que el arreglo monthtable puede ser {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} o {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} dependiendo de si el año es bisiesto o no…
Más claro? Bueno, léelo con detención.. el código se explica a si mismo mejor de lo que yo te lo puedo tratar de explicar.

hashing

DesaprobarAprobar0hashing dijo el 3-1-2009 a las 00:19:

54

@Gon,
si, dicen que a veces el mejor código es NO ESCRIBIR código… a veces aplica bastante bien.

Felipe

DesaprobarAprobar-1Felipe dijo el 3-1-2009 a las 00:50:

55

juaujajuauja error ql xD
como mierda se les paso xD

Nicolas Goles

DesaprobarAprobar1Nicolas Goles dijo el 3-1-2009 a las 01:02:

56

BOOL ConvertDays(UINT32 days, SYSTEMTIME* lpTime)
{
int dayofweek, month, year;
UINT8 *month_tab;

//Calculate current day of the week
dayofweek = GetDayOfWeek(days);

year = ORIGINYEAR;

while (days > 365) // days = 366 … entra en el while…
{
if (IsLeapYear(year)) // Es biciesto asi que entra en el if ( 366 días )
{
if (days > 366) // el numero de dias NO es mayor a 366 , no entra en el if…
{
days -= 366;
year += 1;
}
}

else // NO entra en el else y se re-evalúa la condición del while. days sigue siendo > a 365, por lo que cae en el inf loop.
{
days -= 365;
year += 1;
}
}

es trivial de ver este error… Por eso se arregló un día después, por que ahí el if dentro de if ( IsLeapYear(year)) fué válido ( el contador de días llegó a 367). Entonces se decrementó days y aumentó year y listo.

La solución es trivial.

Ah! y para los que hablaban de C# , no son muchos ( que yo conozca ) , los dispositivos móbiles que tienen la Virtual Machine ( Common Language Runtime) instalada… te gastaría rapidito la batería del zune… por eso al final C la lleva jajaja

Saludos :)

PD : No pude identar bien el código, se re-identa solo.

Guillermo

DesaprobarAprobar4Guillermo dijo el 3-1-2009 a las 01:17:

57

@hashing exacto, pero si le pones un if (days >= 366) entrara al if con el indice en 366 y al restarle 366 el indice de dias te queda en 0, que dia del año es el dia 0?

carlos

DesaprobarAprobar3carlos dijo el 3-1-2009 a las 01:57:

58

soy programador…y si el error es tonto, de alguna manera para los que entienden, mi pregunta va mas alla, listo se vio el error (sea tonto o no, ese es otro tema….) pero porque solo en los modelos de 30 gigas..que paso con los demas, acaso los demas tienen programacion diferente , se programa cada modelo desde cero, lo dudo..algo debe pasar en los modelos de programacion de microsoft…vamos, los que saben programar saben que empresa que se respete tiene equipos de desarrollo, algo debe pasar para que ese error se colara, porque microsoft tiene su framework .net y ahi hay muchas librerias que manejan fechas, porque escribir el codigo de nuevo…en fin…son solo cosas que me dan vueltas en la cabeza…

hashing

DesaprobarAprobar0hashing dijo el 3-1-2009 a las 03:14:

59

@Guillermo,
disculpa, no entendí para nada tu post anterior.
Lo que apuntas es cierto, por eso mi queja anterior, sin haber visto cómo cerraba el ciclo, si agregabas una condición más antes de cerrar el while – if(days==366 && IsLeapYear(year)) break; – no existía el error. Evidentemente hay soluciones más elegantes, de todos modos. Por otra parte, como bien señalas, es trivial ver que el <= lleva a otro bug (no un loop infinito, de todos modos).

Temo

DesaprobarAprobar2Temo dijo el 3-1-2009 a las 03:30:

60

De hecho, voy a revelarles el verdadero codigo del error:

if dia=”31 de diciembre de 2008″ and ipod=”sigue dominando el mercado” then
unload me() or killmyself(dont wake me up)
end if

Jaja q mensada, pero asi es…

Deja tu Comentario

XHTML: Puedes usar: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Previsualizar comentario?