[vdr] vdr 1.3.25 thread problems

Darren Salt linux at youmustbejoking.demon.co.uk
Wed Jun 1 23:43:15 CEST 2005


I demand that Rainer Zocholl may or may not have written...

> Darren Salt  01.06.05 20:28
>> I demand that Rainer Zocholl may or may not have written...
>>> Again:
>>> The most beloved problem: Reentrancy...

>>> This C-Function in tools.c looks suspicious:

>>> cString TimeToString(time_t t)
>>> {
>>>   char buffer[32];
>>>   if (ctime_r(&t, buffer)) {
>>>      buffer[strlen(buffer) - 1] = 0; // strip trailing newline
>>>      return buffer;
>>>      }
>>>   return "???";
>>> }

>> That's harmless.

> On the first view it does not look so ;-)

True. That's one of the features of C++ ;-)

>> Those return statements are effectively 'return cString (<string>,
>> false)', and the cString constructor will call strdup() if its second
>> parameter is false (and note that that parameter is declared as having a
>> default value).

> Ah, ok, but's not very effective to copy each string several times IMHO.

You have something which is guaranteed to be freeable by the destructor...

> Pardon my stupid question:
> And who is freeing that malloced memory later?

The caller, as soon as the object goes out of scope (the compiler will
automatically insert a call to the object's destructor at that point).

> for example:

> cTDT::cTDT(const u_char *Data)
> :SI::TDT(Data, false)
> {
[snip]
>      isyslog("System Time = %s (%ld)\n", *TimeToString(loctim),loctim);
>      isyslog("Local Time  = %s (%ld)\n", *TimeToString(sattim),sattim);
[snip; no obvious free or delete]
> }

> The pointer is not stored anywhere.
> (At least not obviously)

There's no visible pointer: TimeToString() returns cString, not cString*.
What looks like a dereference is really cString::operator*().

The object is in temporary storage somewhere. It goes out of scope just after
the isyslog() call is completed.

> cString strescape(const char *s, const char *chars)
> {
>   char *buffer;
>   const char *p = s;
>   char *t = NULL;
>   while (*p) {
>         if (strchr(chars, *p)) {
>            if (!t) {
>               buffer = MALLOC(char, 2 * strlen(s) + 1);
>               t = buffer + (p - s);
[snip]
>   return cString(s, t != NULL);
> }

> What happens if the malloc fails?
> VDR will coredump because of the "*t++"

That is likely, but it could happen even if the malloc succeeded if the
system is really short of memory - though this depends on the overcommit
setting, as exposed in /proc/sys/vm/overcommit_memory or the equivalent
sysctl. See the kernel documentation for more information.

> by intention?

Probably not :-)

> Pardon again the stupid question: where/how is that memory freed?

In this case, when the cString object is deleted - have a look at its
constructor and destructor.

> recording.c:

> void cRecordingUserCommand::InvokeCommand(const char *State, const char *RecordingFileName)
> {
>   if (command) {
>      char *cmd;
>      asprintf(&cmd, "%s %s \"%s\"", command, State, *strescape(RecordingFileName, "\"$"));
>      isyslog("executing '%s'", cmd);
>      SystemExec(cmd);
>      free(cmd);
>      }
> }

> Does asprintf know it can release the memory?

The content of cmd (on entry) is undefined and is ignored.

(BTW, I'm not a C++ expert either.)

-- 
| Darren Salt | nr. Ashington, | d youmustbejoking,demon,co,uk
| Debian,     | Northumberland | s zap,tartarus,org
| RISC OS     | Toon Army      | @                      Say NO to UK ID cards
|                                                       http://www.no2id.net/

Never be first. Never be last. Hope that there are more than two entrants.



More information about the vdr mailing list