Bug Summary

File:home/maarten/src/libreoffice/core/odk/source/unoapploader/unx/unoapploader.c
Warning:line 213, column 15
Potential leak of memory pointed to by 'envstr'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name unoapploader.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -std=gnu89 -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c /home/maarten/src/libreoffice/core/odk/source/unoapploader/unx/unoapploader.c
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <stdlib.h>
21#include <unistd.h>
22#include <stdio.h>
23#include <string.h>
24#include <sys/stat.h>
25
26#ifdef LINUX1
27#define __USE_GNU
28#endif
29#include <dlfcn.h>
30
31#include <cppuhelper/findsofficepath.h>
32#include <rtl/string.h>
33#include <sal/types.h>
34
35static char* getPath(void);
36static char* createCommandName( char* argv0 );
37
38static const int SEPARATOR = '/';
39static const char* PATHSEPARATOR = ":";
40
41
42/*
43 * The main function implements a loader for applications which use UNO.
44 *
45 * <p>This code runs on the Unix/Linux platforms only.</p>
46 *
47 * <p>The main function detects a UNO installation on the system and adds the
48 * relevant directories of the installation to the LD_LIBRARY_PATH environment
49 * variable. After that, the application process is loaded and started, whereby
50 * the new process inherits the environment of the calling process, including
51 * the modified LD_LIBRARY_PATH environment variable. The application's
52 * executable name must be the same as the name of this executable, prefixed
53 * by '_'.</p>
54 * <p>On MACOSX DYLD_LIBRARY_PATH is used instead of LD_LIBRARY_PATH!<p>
55 *
56 * <p>A UNO installation can be specified by the user by setting the UNO_PATH
57 * environment variable to the program directory of the UNO installation.
58 * If no installation is specified by the user, the default installation on
59 * the system will be taken. The default installation is found from the
60 * PATH environment variable. This requires that the 'soffice' executable or
61 * a symbolic link is in one of the directories listed in the PATH environment
62 * variable.</p>
63 */
64int main( int argc, char *argv[] )
65{
66 char* path;
67 char* cmdname;
68
69 (void) argc; /* avoid warning about unused parameter */
70
71 /* get the path of the UNO installation */
72 path = getPath();
73
74 if ( path
0.1
'path' is not equal to NULL
!= NULL((void*)0) )
1
Taking true branch
75 {
76#if defined(MACOSX)
77 static const char* ENVVARNAME = "DYLD_LIBRARY_PATH";
78#elif defined(AIX)
79 static const char* ENVVARNAME = "LIBPATH";
80#else
81 static const char* ENVVARNAME = "LD_LIBRARY_PATH";
82#endif
83 char* libpath;
84 char* value;
85 char* envstr;
86 int size;
87
88 size_t pathlen = strlen(path);
89 struct stat stats;
90 int ret;
91
92 static char const unoinfoSuffix[] = "/unoinfo";
93 char * unoinfo = malloc(
94 pathlen + RTL_CONSTASCII_LENGTH(unoinfoSuffix)((sal_Int32)((sizeof (unoinfoSuffix) / sizeof ((unoinfoSuffix
)[0]))-1))
+ 1);
95 /*TODO: overflow */
96 if (unoinfo == NULL((void*)0)) {
2
Assuming 'unoinfo' is not equal to NULL
3
Taking false branch
97 free(path);
98 fprintf(stderrstderr, "Error: out of memory!\n");
99 exit(EXIT_FAILURE1);
100 }
101 strcpy(unoinfo, path);
102 strcpy(
103 unoinfo + pathlen,
104 unoinfoSuffix + (pathlen == 0 || path[pathlen - 1] != '/' ? 0 : 1));
4
Assuming 'pathlen' is equal to 0
105 ret = lstat(unoinfo, &stats);
106 free(unoinfo);
107
108 if (ret == 0) {
5
Assuming 'ret' is not equal to 0
6
Taking false branch
109 char * cmd = malloc(
110 2 * pathlen + RTL_CONSTASCII_LENGTH("/unoinfo c++")((sal_Int32)((sizeof ("/unoinfo c++") / sizeof (("/unoinfo c++"
)[0]))-1))
+ 1);
111 /*TODO: overflow */
112 char const * p;
113 char * q;
114 FILE * f;
115 size_t n = 1000;
116 size_t old = 0;
117 if (cmd == NULL((void*)0)) {
118 fprintf(stderrstderr, "Error: out of memory!\n");
119 exit(EXIT_FAILURE1);
120 }
121 p = path;
122 q = cmd;
123 while (*p != '\0') {
124 *q++ = '\\';
125 *q++ = *p++;
126 }
127 if (p == path || p[-1] != '/') {
128 *q++ = '/';
129 }
130 strcpy(q, "unoinfo c++");
131 f = popen(cmd, "r");
132 free(cmd);
133 if (f == NULL((void*)0))
134 {
135 fprintf(stderrstderr, "Error: calling unoinfo failed!\n");
136 exit(EXIT_FAILURE1);
137 }
138 libpath = NULL((void*)0);
139 for (;;) {
140 size_t m;
141 libpath = realloc(libpath, n);
142 if (libpath == NULL((void*)0)) {
143 fprintf(
144 stderrstderr,
145 "Error: out of memory reading unoinfo output!\n");
146 exit(EXIT_FAILURE1);
147 }
148 m = fread(libpath + old, 1, n - old - 1, f);
149 if (m != n - old - 1) {
150 if (ferror(f)) {
151 fprintf(stderrstderr, "Error: cannot read unoinfo output!\n");
152 exit(EXIT_FAILURE1);
153 }
154 libpath[old + m] = '\0';
155 break;
156 }
157 if (n >= SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul) / 2) {
158 fprintf(
159 stderrstderr,
160 "Error: out of memory reading unoinfo output!\n");
161 exit(EXIT_FAILURE1);
162 }
163 old = n - 1;
164 n *= 2;
165 }
166 if (pclose(f) != 0) {
167 fprintf(stderrstderr, "Error: executing unoinfo failed!\n");
168 exit(EXIT_FAILURE1);
169 }
170 free(path);
171 }
172 else
173 {
174 /* Assume an old OOo 2.x installation without unoinfo: */
175 libpath = path;
176 }
177
178 value = getenv( ENVVARNAME );
179
180 // workaround for finding wrong libsqlite3.dylib in the office installation
181 // For MacOS > 10.6 nss uses the system lib -> unresolved symbol _sqlite3_wal_checkpoint
182#ifdef MACOSX
183 size = strlen( ENVVARNAME ) + strlen( "=/usr/lib:" ) + strlen( libpath ) + 1;
184#else
185 size = strlen( ENVVARNAME ) + strlen( "=" ) + strlen( libpath ) + 1;
186#endif
187 if ( value != NULL((void*)0) )
7
Assuming 'value' is equal to NULL
8
Taking false branch
188 size += strlen( PATHSEPARATOR ) + strlen( value );
189 envstr = (char*) malloc( size );
9
Memory is allocated
190 strcpy( envstr, ENVVARNAME );
191#ifdef MACOSX
192 strcat( envstr, "=/usr/lib:" );
193#else
194 strcat( envstr, "=" );
195#endif
196 strcat( envstr, libpath );
197 free( libpath );
198 if ( value
9.1
'value' is equal to NULL
!= NULL((void*)0) )
10
Taking false branch
199 {
200 strcat( envstr, PATHSEPARATOR );
201 strcat( envstr, value );
202 }
203 /* coverity[tainted_data : FALSE] */
204 putenv( envstr );
205 }
206 else
207 {
208 fprintf( stderrstderr, "Warning: no office installation found!\n" );
209 fflush( stderrstderr );
210 }
211
212 /* set the executable name for the application process */
213 cmdname = createCommandName( argv[0] );
11
Potential leak of memory pointed to by 'envstr'
214 argv[0] = cmdname;
215
216 /*
217 * create the application process;
218 * if successful, execvp doesn't return to the calling process
219 */
220 /* coverity[tainted_string] - createCommandName creates a safe string */
221 execvp( cmdname, argv );
222 fprintf( stderrstderr, "Error: execvp failed!\n" );
223 fflush( stderrstderr );
224
225 return 0;
226}
227
228/*
229 * Gets the path of a UNO installation.
230 *
231 * @return the installation path or NULL, if no installation was specified or
232 * found, or if an error occurred.
233 * Returned pointer must be released with free()
234 */
235char* getPath(void)
236{
237 char* path = cppuhelper_detail_findSofficePath();
238
239 if ( path == NULL((void*)0) )
240 {
241 fprintf( stderrstderr, "Warning: getting path from PATH environment "
242 "variable failed!\n" );
243 fflush( stderrstderr );
244 }
245
246 return path;
247}
248
249/*
250 * Creates the application's executable file name.
251 *
252 * <p>The application's executable file name is the name of this executable
253 * prefixed by '_'.</p>
254 *
255 * @param argv0 specifies the argv[0] parameter of the main function
256 *
257 * @return the application's executable file name or NULL, if an error occurred
258 */
259char* createCommandName( char* argv0 )
260{
261 const char* CMDPREFIX = "_";
262 const char* prgname = NULL((void*)0);
263
264 char* cmdname = NULL((void*)0);
265 char* sep = NULL((void*)0);
266#ifndef AIX
267 Dl_info dl_info;
268#endif
269
270 /* get the executable file name from argv0 */
271 prgname = argv0;
272
273#ifndef AIX
274 /*
275 * if argv0 doesn't contain an absolute path name, try to get the absolute
276 * path name from dladdr; note that this only works for Solaris, not for
277 * Linux
278 */
279 if ( argv0 != NULL((void*)0) && *argv0 != SEPARATOR &&
280 dladdr( (void*) &createCommandName, &dl_info ) &&
281 dl_info.dli_fname != NULL((void*)0) && *dl_info.dli_fname == SEPARATOR )
282 {
283 prgname = dl_info.dli_fname;
284 }
285#endif
286
287 /* prefix the executable file name by '_' */
288 if ( prgname != NULL((void*)0) )
289 {
290 cmdname = (char*) malloc( strlen( prgname ) + strlen( CMDPREFIX ) + 1 );
291 sep = strrchr( prgname, SEPARATOR );
292 if ( sep != NULL((void*)0) )
293 {
294 int pos = ++sep - prgname;
295 strncpy( cmdname, prgname, pos );
296 cmdname[ pos ] = '\0';
297 strcat( cmdname, CMDPREFIX );
298 strcat( cmdname, sep );
299 }
300 else
301 {
302 strcpy( cmdname, CMDPREFIX );
303 strcat( cmdname, prgname );
304 }
305 }
306
307 return cmdname;
308}
309
310/* vim:set shiftwidth=4 softtabstop=4 expandtab: */