Changeset 10483 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Sep 7, 2005, 4:27:28 PM (20 years ago)
Author:
ggaren
Message:

-fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4781
Date.setMonth fails with big values due to overflow

Reviewed by darin.

  • kjs/date_object.cpp: (timetUsingCF): for consistency, changed return statement to invalidDate instead of LONG_MAX (KJS::fillStructuresUsingTimeArgs): modified for readability (KJS::fillStructuresUsingDateArgs): new function analogous to fillStructuresUsingTimeArgs (KJS::DateProtoFuncImp::callAsFunction): modified to use fillStructuresUsingDateArgs (KJS::DateObjectImp::construct): moved variable declaration to proper scope (KJS::DateObjectFuncImp::callAsFunction): moved variable declaration to proper scope
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/date_object.cpp

    r10457 r10483  
    202202    CFTimeInterval interval = absoluteTime + kCFAbsoluteTimeIntervalSince1970;
    203203    if (interval > LONG_MAX) {
    204         interval = LONG_MAX;
     204        return invalidDate;
    205205    }
    206206
     
    404404}
    405405
    406 static double timeFromArgs(ExecState *exec, const List &args, int maxArgs, double ms, struct tm *t)
    407 {
    408     double result = 0;
     406// Converts a list of arguments sent to a Date member function into milliseconds, updating
     407// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
     408//
     409// Format of member function: f([hour,] [min,] [sec,] [ms])
     410static void fillStructuresUsingTimeArgs(ExecState *exec, const List &args, int maxArgs, double *ms, struct tm *t)
     411{
     412    double milliseconds = 0;
    409413    int idx = 0;
    410414    int numArgs = args.size();
    411415   
    412     // process up to max_args arguments
     416    // JS allows extra trailing arguments -- ignore them
    413417    if (numArgs > maxArgs)
    414418        numArgs = maxArgs;
     419
    415420    // hours
    416421    if (maxArgs >= 4 && idx < numArgs) {
    417422        t->tm_hour = 0;
    418         result = args[idx++]->toInt32(exec) * msPerHour;
    419     }
     423        milliseconds += args[idx++]->toInt32(exec) * msPerHour;
     424    }
     425
    420426    // minutes
    421427    if (maxArgs >= 3 && idx < numArgs) {
    422428        t->tm_min = 0;
    423         result += args[idx++]->toInt32(exec) * msPerMinute;
    424     }
     429        milliseconds += args[idx++]->toInt32(exec) * msPerMinute;
     430    }
     431   
    425432    // seconds
    426433    if (maxArgs >= 2 && idx < numArgs) {
    427434        t->tm_sec = 0;
    428         result += args[idx++]->toInt32(exec) * msPerSecond;
    429     }
    430     // read ms from args if present or add the old value
    431     result += idx < numArgs ? roundValue(exec, args[idx]) : ms;
    432            
    433     return result;
     435        milliseconds += args[idx++]->toInt32(exec) * msPerSecond;
     436    }
     437   
     438    // milliseconds
     439    if (idx < numArgs) {
     440        milliseconds += roundValue(exec, args[idx]);
     441    } else {
     442        milliseconds += *ms;
     443    }
     444   
     445    *ms = milliseconds;
     446}
     447
     448// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
     449// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
     450//
     451// Format of member function: f([years,] [months,] [days])
     452static void fillStructuresUsingDateArgs(ExecState *exec, const List &args, int maxArgs, double *ms, struct tm *t)
     453{
     454  int idx = 0;
     455  int numArgs = args.size();
     456 
     457  // JS allows extra trailing arguments -- ignore them
     458  if (numArgs > maxArgs)
     459    numArgs = maxArgs;
     460 
     461  // years
     462  if (maxArgs >= 3 && idx < numArgs) {
     463    t->tm_year = args[idx++]->toInt32(exec) - 1900;
     464  }
     465 
     466  // months
     467  if (maxArgs >= 2 && idx < numArgs) {
     468    int months = args[idx++]->toInt32(exec);
     469
     470    // t->tm_year must hold the bulk of the data to avoid overflow when converting
     471    // to a CFGregorianDate. (CFGregorianDate.month is an SInt8; CFGregorianDate.year is an SInt32.)
     472    t->tm_year += months / 12;
     473    t->tm_mon = months % 12;
     474  }
     475 
     476  // days
     477  if (idx < numArgs) {
     478    t->tm_mday = 0;
     479    *ms += args[idx]->toInt32(exec) * msPerDay;
     480  }
    434481}
    435482
     
    723770    break;
    724771  case SetMilliSeconds:
    725     ms = roundValue(exec, args[0]);
     772    fillStructuresUsingTimeArgs(exec, args, 1, &ms, t);
    726773    break;
    727774  case SetSeconds:
    728     ms = timeFromArgs(exec, args, 2, ms, t);
     775    fillStructuresUsingTimeArgs(exec, args, 2, &ms, t);
    729776    break;
    730777  case SetMinutes:
    731     ms = timeFromArgs(exec, args, 3, ms, t);
     778    fillStructuresUsingTimeArgs(exec, args, 3, &ms, t);
    732779    break;
    733780  case SetHours:
    734     ms = timeFromArgs(exec, args, 4, ms, t);
     781    fillStructuresUsingTimeArgs(exec, args, 4, &ms, t);
    735782    break;
    736783  case SetDate:
    737       t->tm_mday = 0;
    738       ms += args[0]->toInt32(exec) * msPerDay;
    739       break;
     784    fillStructuresUsingDateArgs(exec, args, 1, &ms, t);
     785    break;
    740786  case SetMonth:
    741     t->tm_mon = args[0]->toInt32(exec);
    742     if (args.size() >= 2)
    743       t->tm_mday = args[1]->toInt32(exec);
     787    fillStructuresUsingDateArgs(exec, args, 2, &ms, t);   
    744788    break;
    745789  case SetFullYear:
    746     t->tm_year = args[0]->toInt32(exec) - 1900;
    747     if (args.size() >= 2)
    748       t->tm_mon = args[1]->toInt32(exec);
    749     if (args.size() >= 3)
    750       t->tm_mday = args[2]->toInt32(exec);
     790    fillStructuresUsingDateArgs(exec, args, 3, &ms, t);
    751791    break;
    752792  case SetYear:
     
    823863          value = args[0]->toPrimitive(exec)->toNumber(exec);
    824864  } else {
    825     struct tm t;
    826     memset(&t, 0, sizeof(t));
    827865    if (isNaN(args[0]->toNumber(exec))
    828866        || isNaN(args[1]->toNumber(exec))
     
    834872      value = NaN;
    835873    } else {
     874      struct tm t;
     875      memset(&t, 0, sizeof(t));
    836876      int year = args[0]->toInt32(exec);
    837877      t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
     
    893933  }
    894934  else { // UTC
    895     struct tm t;
    896     memset(&t, 0, sizeof(t));
    897935    int n = args.size();
    898936    if (isNaN(args[0]->toNumber(exec))
     
    905943      return Number(NaN);
    906944    }
     945
     946    struct tm t;
     947    memset(&t, 0, sizeof(t));
    907948    int year = args[0]->toInt32(exec);
    908949    t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
Note: See TracChangeset for help on using the changeset viewer.