Bug Summary

File:pending_notifications.c
Location:line 50, column 10
Description:Potential memory leak

Annotated Source Code

1/* -*- c++ -*-
2Copyright (C) 2004-2013 Christian Wieninger
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18
19The author can be reached at cwieninger@gmx.de
20
21The project's page is at http://winni.vdr-developer.org/epgsearch
22*/
23
24#include <string>
25#include "pending_notifications.h"
26#include "epgsearchtools.h"
27
28
29cPendingNotifications PendingNotifications;
30char *cPendingNotification::buffer = NULL__null;
31// -- cPendingNotifications -----------------------------------------------------------------
32
33cPendingNotification::~cPendingNotification(void)
34{
35 if (buffer) {
36 free(buffer);
37 buffer = NULL__null;
38 }
39}
40bool cPendingNotification::Parse(const char *s)
41{
42 char *t = skipspace(s + 1);
43 switch (*s) {
17
Control jumps to 'case 70:' at line 44
44 case 'F': strreplace(t, '|', '\n');
45 formatted = strdup(t);
18
Memory is allocated
46 break;
19
Execution continues on line 50
47 default: LogFile.eSysLog("ERROR: unexpected tag while reading epgsearch pending notifications data: %s", s);
48 return false;
49 }
50 return true;
20
Potential memory leak
51}
52
53bool cPendingNotification::Read(FILE *f)
54{
55 cPendingNotification *p = NULL__null;
56 char *s;
57 cReadLine ReadLine;
58 while ((s = ReadLine.Read(f)) != NULL__null) {
7
Loop condition is true. Entering loop body
14
Loop condition is true. Entering loop body
59 char *t = skipspace(s + 1);
60 switch (*s) {
8
Control jumps to 'case 78:' at line 61
15
Control jumps to the 'default' case at line 103
61 case 'N': if (!p) {
9
Taking true branch
62 tEventID EventID;
63 int Type, TimerMod, SearchID;
64 time_t Start;
65 int n = sscanf(t, "%d %u %d %d %ld", &Type, &EventID, &TimerMod, &SearchID, &Start);
66 if (n == 5) {
10
Assuming 'n' is equal to 5
11
Taking true branch
67 p = new cPendingNotification;
68 if (p)
12
Taking true branch
69 {
70 p->type = Type;
71 p->eventID = EventID;
72 p->timerMod = TimerMod;
73 p->searchID = SearchID;
74 p->start = Start;
75
76 PendingNotifications.Add(p);
77 }
78 }
79 }
80 break;
13
Execution continues on line 58
81 case 'C':
82 {
83 s = skipspace(s + 1);
84 char *pC = strchr(s, ' ');
85 if (pC)
86 *pC = 0; // strips optional channel name
87 if (*s) {
88 tChannelID channelID = tChannelID::FromString(s);
89 if (channelID.Valid()) {
90 if (p)
91 p->channelID = channelID;
92 }
93 else {
94 LogFile.Log(3, "ERROR: illegal channel ID: %s", s);
95 return false;
96 }
97 }
98 }
99 break;
100 case 'n':
101 p = NULL__null;
102 break;
103 default: if (p && !p->Parse(s))
16
Calling 'cPendingNotification::Parse'
104 {
105 LogFile.Log(1,"ERROR: parsing %s", s);
106 return false;
107 }
108 }
109 }
110 return true;
111}
112
113
114const char *cPendingNotification::ToText(void) const
115{
116 char* tmpFormatted = formatted!=""?strdup(formatted.c_str()):NULL__null;
117 if (tmpFormatted)
118 strreplace(tmpFormatted, '\n', '|');
119
120 if (buffer)
121 free(buffer);
122 buffer = NULL__null;
123
124 cChannel *channel = Channels.GetByChannelID(channelID, true, true);
125 if (!channel)
126 LogFile.Log(3,"invalid channel in pending notifications!");
127
128 msprintf(&buffer, "N %d %u %d %d %ld\nC %s\n%s%s%sn",
129 type, eventID, timerMod, searchID, start,
130 channel?CHANNELSTRING(channel)(*channel->GetChannelID().ToString()):"",
131 tmpFormatted?"F ":"",tmpFormatted?tmpFormatted:"", tmpFormatted?"\n":"");
132
133 if (tmpFormatted)
134 free(tmpFormatted);
135
136 return buffer;
137}
138
139bool cPendingNotification::Save(FILE *f)
140{
141 return fprintf(f, "%s\n", ToText()) > 0;
142}
143
144bool cPendingNotifications::Load(const char *FileName)
145{
146 Clear();
147 if (FileName) {
1
Assuming 'FileName' is null
2
Taking false branch
148 free(fileName);
149 fileName = strdup(FileName);
150 }
151
152 if (fileName && access(fileName, F_OK0) == 0) {
3
Taking true branch
153 LogFile.iSysLog("loading %s", fileName);
154 FILE *f = fopen(fileName, "r");
155 bool result = false;
156 if (f) {
4
Assuming 'f' is non-null
5
Taking true branch
157 result = cPendingNotification::Read(f);
6
Calling 'cPendingNotification::Read'
158 fclose(f);
159 }
160 if (result)
161 LogFile.Log(2,"loaded pending notifications from %s (count: %d)", fileName, Count());
162 else
163 LogFile.Log(1,"error loading pending notifications from %s (count: %d)", fileName, Count());
164 return result;
165 }
166 return false;
167}
168
169bool cPendingNotifications::Save(void)
170{
171 bool result = true;
172 cPendingNotification* l = (cPendingNotification*)this->First();
173 cSafeFile f(fileName);
174 if (f.Open()) {
175 while (l) {
176 if (!l->Save(f)) {
177 result = false;
178 break;
179 }
180 l = (cPendingNotification*)l->Next();
181 }
182 if (!f.Close())
183 result = false;
184 }
185 else
186 result = false;
187 LogFile.Log(2,"saved pending notifications (count: %d)", Count());
188 return result;
189}
190
191