On Tue, Jul 09, 2013 at 12:50:00PM +0200, Laszlo Ersek wrote:
> On 07/09/13 11:26, Gary Ching-Pang Lin wrote:
> > Per gmtime manpage, tm_mon is the number of months since January
> > while MonthNo is the month of the year, so tm_mon should be MonthNo-1.
> >
> > Also, tm_mday is the day of the month, and DayNo is the number of
> > days since the first day of the month. Assigning DayNo+1 to tm_mday
> > to fix the definition.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Gary Ching-Pang Lin <g...@suse.com>
> > ---
> >  CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c 
> > b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> > index 805e6b4..15be4ef 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> > +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> > @@ -154,8 +154,8 @@ struct tm * gmtime (const time_t *timer)
> >      }
> >    }
> >
> > -  GmTime->tm_mon  = (int) MonthNo;
> > -  GmTime->tm_mday = (int) DayNo;
> > +  GmTime->tm_mon  = (int) MonthNo - 1;
> > +  GmTime->tm_mday = (int) DayNo + 1;
> >
> >    GmTime->tm_isdst  = 0;
> >    GmTime->tm_gmtoff = 0;
> >
> 
> "DayNo" is the number of whole days passed since the Epoch.
> 
> In the gmtime() function, the first loop subtracts whole years. At the
> end of the loop, DayNo may be zero (eg. 01-Jan-1971). After the loop,
> "DayNo" contains the number of whole days passed in the new year.
> 
> The second loop wants to find out the number of whole months passed in
> the new year, and the number of remaining days. Again, the number of
> days remaining in the month could be 0 in theory (eg. for 01-Feb-1970).
> 
>   for (MonthNo = 12; MonthNo > 1; MonthNo--) {
>     if (DayNo > CumulativeDays[IsLeap(Year)][MonthNo]) {
>       DayNo = (UINT16) (DayNo - (UINT16) 
> (CumulativeDays[IsLeap(Year)][MonthNo]));
>       break;
>     }
>   }
> 
> For 01-Feb-1970, DayNo == 31 before the second loop. In the second loop,
> for MonthNo==2, CumulativeDays[0][2] == 31, hence we don't break out,
> and MonthNo is decreased to 1. Thereafter the controlling expression
> stops the loop (with MonthNo==1, DayNo==31):
> 
>          should be  pre-patch  post-patch
> tm_mon           1          1           0
> tm_mday          1         31          32
> 
> I think both pre-patch and post-patch results are wrong (although the
> post-patch version is correct "quantitatively", as Feb 1st is in fact
> the 32nd day of January).
> 
> The thing to fix (in addition to the patch) is the relational operator
> in the loop: if the number of our remaining *whole* days is greater than
> *or equal to* the cumulative days up to and including MonthNo, then
> month MonthNo itself has passed too. (Note that MonthNo==12 corresponds
> to November.)
> 
> When the second loop, modified thus, terminates, MonthNo==1 implies that
> *stricly less* than 31 days have passed in the new year, hence we're
> still in January. DayNo keeps its meaning (and MonthNo==1 && DayNo==0
> corresponds to Jan 1st).
> 
Ah, right! The modified condition fixed the case I missed.
Thanks for pointing it out, Laszlo :)

Gary Lin

> I think the patch is a step in the right direction but incomplete; I
> suggest:
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c 
> b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> index 805e6b4..6422d61 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
> @@ -148,14 +148,14 @@ struct tm * gmtime (const time_t *timer)
>    GmTime->tm_yday = (int) DayNo;
> 
>    for (MonthNo = 12; MonthNo > 1; MonthNo--) {
> -    if (DayNo > CumulativeDays[IsLeap(Year)][MonthNo]) {
> +    if (DayNo >= CumulativeDays[IsLeap(Year)][MonthNo]) {
>        DayNo = (UINT16) (DayNo - (UINT16) 
> (CumulativeDays[IsLeap(Year)][MonthNo]));
>        break;
>      }
>    }
> 
> -  GmTime->tm_mon  = (int) MonthNo;
> -  GmTime->tm_mday = (int) DayNo;
> +  GmTime->tm_mon  = (int) MonthNo - 1;
> +  GmTime->tm_mday = (int) DayNo + 1;
> 
>    GmTime->tm_isdst  = 0;
>    GmTime->tm_gmtoff = 0;
> 
> This is identical to your patch for all days except for Feb 1st, Mar
> 1st, ... Dec 1st, where my suggested version returns DayNo==0
> (-->tm_mday==1), and the next month relative to yours.
> 
> Laszlo
> 

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to