View Issue Details

IDProjectCategoryView StatusLast Update
0002066unrealdocumentationpublic2015-07-13 10:42
ReporterTrocoAssigned Tosyzop 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformwin32OSXP ProfessionalOS Version5.1 - 2600
Product Version 
Target VersionFixed in Version3.4-alpha1 
Summary0002066: ircsprintf error
DescriptionIf you use ircsprintf(tmp, "%lu", strtoul("4", NULL, 10)); for example, tmp is "1". So, it occurs with 1 to 5.
In ircsprintf.c, you can see
if (v1 < 6L)
    switch (v1)
    {
        case 0L:
            *str++ = '0';
            continue;
        case 1L:
            *str++ = '1';
            continue;
        case 2L:
            *str++ = '1';
            continue;
        case 3L:
            *str++ = '1';
            continue;
        case 4L:
            *str++ = '1';
            continue;
        case 5L:
            *str++ = '1';
            continue;
    }
So, as you imagine, everytime you use "1", "2", "3", "4" and "5" as unsigned long, you'll obtain "1". Is there a reason for that?
TagsNo tags attached.
3rd party modules

Activities

Troco

2004-09-12 20:29

reporter   ~0007628

Sorry, is not a documentation bug.
It's an inconvenience for coders, due to we can't manage unsigned longs by ircsprintf.

syzop

2004-09-13 18:31

administrator   ~0007644

code: shall we just remove the <6L part? Also, what to do with == 0? :p

== UNREAL ==
if (c == 'l' && *format == 'u') /* Prints time_t value in interval
                   [ 100000000 , 4294967295 ]
                   Actually prints like "%09lu" */
{
    unsigned long v1, v2;
    const char *ap;
    ++format;
    v1 = va_arg(vl, unsigned long);
    /* Fixed to work with %lu == 0 --Stskeeps */
    if (v1 == 0L)
    {
        *str++ = '0';
        continue;
    }
    if (v1 < 6L)
        switch (v1)
        {
          case 0L:
              *str++ = '0';
              continue;
          case 1L:
              *str++ = '1';
              continue;
          case 2L:
              *str++ = '1';
              continue;
          case 3L:
              *str++ = '1';
              continue;
          case 4L:
              *str++ = '1';
              continue;
          case 5L:
              *str++ = '1';
              continue;
        }
    if (v1 > 999999999L)
    {
        v2 = v1 / 1000000000;
        v1 -= v2 * 1000000000;
        *str++ = '0' + v2;
    }
    v2 = v1 / 1000000;
    v1 -= v2 * 1000000;
    ap = atoi_tab + (v2 << 2);
    *str++ = *ap++;
    *str++ = *ap++;
[etc]

== HYBRID ==
 /*
  * Prints time_t value in interval
  * [ 100000000 , 4294967295 ]
  * Actually prints like "%09lu"
  */
 if (c == 'l' && *format == 'u')
   {
     unsigned long v1, v2;
     const char *ap;

     ++format;
     v1 = va_arg(args, unsigned long);
     if (v1 == 0)
     {
       *str++ = '0';
       ++bytes;
       continue;
     }
     if (v1 > 999999999L)
   {
     v2 = v1 / 1000000000;
     v1 -= v2 * 1000000000;
     *str++ = '0' + v2;
     ++bytes;
   }

     v2 = v1 / 1000000;
     v1 -= v2 * 1000000;
     ap = atoi_tab + (v2 << 2);
     *str++ = *ap++;
     *str++ = *ap++;
     *str++ = *ap;
[etc]

On a sidenote, I presume this %09lu stuff has a good reason (else I guess hybrid/etc would have removed it long ago), but still I find it quite annoying if I print an %lu that it suddenly becomes %09lu! ;p.

Troco

2004-09-13 18:52

reporter   ~0007646

Yes, I'm totally agree with you. If you use %lu, it doesn't make sense to print %09lu. I would remove this stuff and leave only == 0 (and it's a waste of bandwith, a bit but unusued.

codemastr

2004-09-13 19:24

reporter   ~0007648

[ 100000000 , 4294967295 ]

That's why it says %09lu. It seems to not be designed for smaller numbers?

Troco

2004-09-19 17:24

reporter   ~0007723

So, what can you do with this trouble?

syzop

2004-09-19 18:35

administrator   ~0007724

This is how it currently counts:
0
1
1
1
1
1
000000006
000000007
000000008
(which is 0,1,2,3,4,5,6,7,8)

As an example of %lu usage I grepped around a bit:
lots of MODE (and TOPIC) TS stuff, but also normal notices like:
sendto_snomask(SNO_EYES, "*** TS fix for %s - %lu(ours) %lu(theirs)",
"*** TS bounce for %s - %lu(ours) %lu(theirs)",
ircsprintf(buffer, "%ludays %luhours %luminutes %lusecs",
sendto_snomask(SNO_EYES, "*** TS fix for %s - %lu(ours) %lu(theirs)",
and, a few more commonly occurences that normal users might see:
src/s_err.c:/* 329 RPL_CREATIONTIME */ ":%s 329 %s %s %lu",
src/s_err.c:/* 333 RPL_TOPICWHOTIME */ ":%s 333 %s %s %s %lu",
src/s_err.c:/* 348 RPL_EXLIST */ ":%s 348 %s %s %s %s %lu",
src/s_err.c:/* 367 RPL_BANLIST */ ":%s 367 %s %s %s %s %lu",

But... since we have pasted Sep 9 2001 (999999999 epoch time) quite a while ago, it's on my small net. hard to find such a occurence ;).

hybrid: does very similar as us, in fact.. it uses it in even some more numerics than we do (~80 occurrences)
bahamut: does not use %09lu stuff anymore for %lu.
ircu: does not use %09lu stuff anymore for %lu. In fact, it seems to got rid of the whole IRC-specific printf stuff and now uses an snprintf alike thing that supports a lot of formats instead of the usual 'support a few fast ones, and pass other ones to system [v]sprintf' thing that other ircds use. This probably has a considerable speed impact (snprintf use + near-full support)

So.. ;)

Anyway, I'll at least rip out the <6L stuff right now.
The 0 = "0" part is not found in the other ircds I checked, although I can understand the idea that, to save bandwidth, a 0 TS shouldn't be send as 9 zero's but as just one "0".

Still, perhaps consider removing this prefixing of zero's? And instead of doing the %09lu stuff make it a real %lu? What do you think codemastr?

codemastr

2004-09-19 18:56

reporter   ~0007725

Well, since a TS can never (hopefully) be below 100000000, I don't see any problem with it...

stskeeps

2007-04-27 06:12

reporter   ~0013861

Still an issue?

falconkirtaran

2013-09-28 10:22

reporter   ~0017774

This can be closed. The code that would do this no longer exists.

Issue History

Date Modified Username Field Change
2004-09-09 21:24 Troco New Issue
2004-09-12 20:29 Troco Note Added: 0007628
2004-09-13 18:31 syzop Note Added: 0007644
2004-09-13 18:52 Troco Note Added: 0007646
2004-09-13 19:24 codemastr Note Added: 0007648
2004-09-19 17:24 Troco Note Added: 0007723
2004-09-19 18:35 syzop Note Added: 0007724
2004-09-19 18:56 codemastr Note Added: 0007725
2007-04-27 06:12 stskeeps Note Added: 0013861
2007-04-27 06:12 stskeeps Status new => feedback
2013-09-28 10:22 falconkirtaran Note Added: 0017774
2014-03-14 01:14 peterkingalexander Issue cloned: 0004282
2015-07-13 10:42 syzop Status feedback => closed
2015-07-13 10:42 syzop Assigned To => syzop
2015-07-13 10:42 syzop Resolution open => fixed
2015-07-13 10:42 syzop Fixed in Version => 3.4-alpha1