Suspicious memory leaks by reviewing the code

Open
#3 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
c, python

Research direction

Start by reading the win32_wchdir and posix_fdopen entry points shown in the issue, tracing every early return after an allocation. Confirm whether each allocated buffer is released on all paths, then use the repository's relevant platform and file-I/O tests to verify the leak fixes without changing successful behavior.

Written by the indexing model from the issue text.

Description

It seems that when coming into the exception branch, perhaps memory leak will happen.

static BOOL __stdcall
win32_wchdir(LPCWSTR path)
{
    wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
    int result;
    wchar_t env[4] = L"=x:";

    if(!SetCurrentDirectoryW(path))
        return FALSE;
    result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
    if (!result)
        return FALSE;
    if (result > MAX_PATH+1) {
        new_path = malloc(result * sizeof(wchar_t));
        if (!new_path) {
            SetLastError(ERROR_OUTOFMEMORY);
            return FALSE;
        }
        result = GetCurrentDirectoryW(result, new_path);
        if (!result) {
            free(new_path);
            return FALSE;
        }
    }
    if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
        wcsncmp(new_path, L"//", 2) == 0)
        /* UNC path, nothing to do. */
        return TRUE;   ################### if new_path calls malloc, it nerver calls free
    env[1] = new_path[0];
    result = SetEnvironmentVariableW(env, new_path);
    if (new_path != _new_path)
        free(new_path);
    return result;
}
static PyObject *
posix_fdopen(PyObject *self, PyObject *args)
{
    int fd;
    char *orgmode = "r";
    int bufsize = -1;
    FILE *fp;
    PyObject *f;
    char *mode;
    if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
        return NULL;

    /* Sanitize mode.  See fileobject.c */
    mode = PyMem_MALLOC(strlen(orgmode)+3);
    if (!mode) {
        PyErr_NoMemory();
        return NULL;
    }
    strcpy(mode, orgmode);
    if (_PyFile_SanitizeMode(mode)) {
        PyMem_FREE(mode);
        return NULL;
    }
    if (!_PyVerify_fd(fd))
        return posix_error();    ################### mode nerver calls PyMem_FREE
    Py_BEGIN_ALLOW_THREADS
#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
    if (mode[0] == 'a') {
        /* try to make sure the O_APPEND flag is set */
        int flags;
        flags = fcntl(fd, F_GETFL);
        if (flags != -1)
            fcntl(fd, F_SETFL, flags | O_APPEND);
        fp = fdopen(fd, mode);
        if (fp == NULL && flags != -1)
            /* restore old mode if fdopen failed */
            fcntl(fd, F_SETFL, flags);
    } else {
        fp = fdopen(fd, mode);
    }
#else
    fp = fdopen(fd, mode);
#endif
    Py_END_ALLOW_THREADS
    PyMem_FREE(mode);
    if (fp == NULL)
        return posix_error();
    /* The dummy filename used here must be kept in sync with the value
       tested against in gzip.GzipFile.__init__() - see issue #13781. */
    f = PyFile_FromFile(fp, "<fdopen>", orgmode, fclose);
    if (f != NULL)
        PyFile_SetBufSize(f, bufsize);
    return f;
}
Dominant language
Python
Stars
3
Forks
12
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from enthought/Python-2.7.3

All issues in enthought/Python-2.7.3

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.