问:
Cant find memory leak in C
I've been sitting for hours checking this code after I found out there's a memory leak/error somewhere
Where is that leak? How can it be fixed?
here is Dr.Memory report:</p>

```<code>Dr. Memory version 2.3.0
         Running "C:\Users\Beni\source\repos\Magshimim_EX8\Debug\Magshimim_EX8.exe"
         Using system call file C:\Users\Beni\AppData\Roaming\Dr. Memory\symcache\syscalls_wow64.txt

         Error #1: UNADDRESSABLE ACCESS: reading 1 byte(s)
         replace_strlen
             d:\drmemory_package\drmemory\replace.c(412):
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         KERNEL32.dll!BaseThreadInitThunk
             ??:0

         ERRORS FOUND:
               1 unique,     1 total unaddressable access(es)
               0 unique,     0 total uninitialized access(es)
               0 unique,     0 total invalid heap argument(s)
               0 unique,     0 total GDI usage error(s)
               0 unique,     0 total handle leak(s)
               0 unique,     0 total warning(s)
               0 unique,     0 total,      0 byte(s) of leak(s)
               0 unique,     0 total,      0 byte(s) of possible leak(s)
         Details: C:\Users\Beni\AppData\Roaming\Dr. Memory\DrMemory-Magshimim_EX8.exe.5208.000\results.txt
         WARNING: application exited with abnormal code 0xc0000005
</code>```

```<code>#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>

#define FALSE 0
#define TRUE !FALSE
#define FIRST_TWO_FILES 2
#define FIRST_TWENTY_PRECENTS 1
#define MIDDLE_SIXTY_PRECENTS 2
#define LAST_TWENTY_PRECENTS 3

long findLenOfFile(FILE * file);
char* readFile(FILE* f, char* dest, long len);
char menu(char* scanFolder, char* virusSignature);
char** writeFilesFromFolder(char* scanFolder, char ** filesList, int* len);
char* writePart(char* src, char* dest, int length, int* newLen, int part);
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen);
void scanFiles(char* scanFolder, char** filesList, int amountOfFiles, char* virusSignature, long virusLength, char option);

int main(int argc, char* argv[])
{
    char* log = malloc(sizeof(char)*strlen(argv[1]) + sizeof(char)*strlen("\\Log.txt") + 4);
    FILE* virusSignatureFile = fopen(argv[2], "rb");
    long virusLength = 0;
    char** filesList = (char**)malloc(sizeof(char) * 0);
    char* virusSignature = 0;
    int amountOfFiles = 0;
    char option = 0;
    int i = 0;

    virusLength = findLenOfFile(virusSignatureFile);

    // get the virusSignature as a string and write the files to check into the filesList
    virusSignature = readFile(virusSignatureFile, virusSignature, virusLength);
    filesList = writeFilesFromFolder(argv[1], filesList, &amountOfFiles);

    // create log file
    strcpy(log, "");
    strcat(log, argv[1]);
    strcat(log, "\\Log.txt");
    FILE * logFile = fopen(log, "w");
    fprintf(logFile, "Anti-virus began! Welcome!\n\nFolder to scan:\n%s\nVirus signature:\n%s\n\nScanning option:\n", argv[1], argv[2]);

    // get scanning option (normal or quick) and continue accordingly
    option = menu(argv[1], argv[2]);
    if (option == '0') {
        fprintf(logFile, "Normal Scan\n\n");
    }
    else {
        fprintf(logFile, "Quick Scan\n\n");
    }
    fprintf(logFile, "Results:\n");
    fclose(logFile);

    // initiate scan
    scanFiles(argv[1], filesList, amountOfFiles, virusSignature, virusLength, option);

    fclose(virusSignatureFile);
    free(log);
    free(filesList);
    free(virusSignature);
    getchar();
    return 0;
}

/*
This function will print the scanning folder path and signature path, also will print the option menu to the user of quick or normal scan,
after that function will return user option(0, or other key)
input: scanFolder path (string), virus signature path (also string)
output: user option (char: '0', or other key)
*/
char menu(char * scanFolder, char * virusSignature)
{
    char userOption = '\0';
    printf("Welcome to my Virus Scan!\n\nFolder to scan: %s\nVirus signature: %s\n\nPress 0 for a norman scan or any other key for a quick scan: ", scanFolder, virusSignature);
    userOption = getchar();
    printf("Scanning began...\nThis process may take several minutes...\n\n");
    return userOption;
}

/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char** writeFilesFromFolder(char * scanFolder, char ** filesList, int* len)
{
    DIR *d = 0;

    struct dirent *dir;
    d = opendir(scanFolder);
    int i = 0;

    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if (i > 1)
            {
                filesList = (char**)realloc(filesList, sizeof(filesList) + sizeof(char*) + 4);
                *(filesList + (i - FIRST_TWO_FILES)) = (char*)malloc(sizeof(char) * strlen(dir->d_name) + 1);
                strcpy(*(filesList + (i - FIRST_TWO_FILES)), (dir->d_name));
            }
            i++;
        }
        closedir(d);
    }
    *len = i - FIRST_TWO_FILES; //first two names is "." and ".."
    return filesList;
}

/*
This function will read the contents of a file into a string
input: a file (FILE *) to read from
output: char* with the contents of the file
*/
char* readFile(FILE* f, char * dest, long len)
{
    dest = (char*)malloc(sizeof(char) * len);
    fread(dest, 1, len, f);
    return dest;
}

void scanFiles(char * scanFolder, char ** filesList, int amountOfFiles, char * virusSignature, long virusLength, char option)
{
    char* log = malloc(sizeof(char)*strlen(scanFolder) + sizeof(char)*strlen("\\Log.txt") + 1);
    char * buffer = (char*)malloc(sizeof(char) * 0);
    char* subBuffer = 0;
    char* slash = "\\";
    long length = 0;
    char* name = 0;
    int subLen = 0;
    int i = 0;
    FILE * f;

    // reopen log file and append to it
    strcpy(log, "");
    strcat(log, scanFolder);
    strcat(log, "\\Log.txt");
    FILE * logFile = fopen(log, "a");

    // iterate over each file
    for (i = 0; i < amountOfFiles; i++)
    {
        name = (char*)malloc(sizeof(char) * strlen(scanFolder) + 1 + sizeof(char) * strlen(slash) + sizeof(char) * strlen(*(filesList + i)) + 20);

        // open current file
        strcpy(name, "");
        strcat(name, scanFolder);
        strcat(name, slash);
        strcat(name, *(filesList + i));
        f = fopen(name, "rb");

        length = findLenOfFile(f);

        if (f != NULL) // if file can be accessed
        {
            buffer = readFile(f, buffer, length);
            if (option == '0') { // Normal Mode
                if (findSignature(virusSignature, buffer, virusLength, length))
                {
                    printf("%s - Infected!\n", name);
                    fprintf(logFile, "%s - Infected!\n", name);
                }
                else
                {
                    printf("%s - Clean\n", name);
                    fprintf(logFile, "%s - Clean\n", name);
                }
            }
            else { // Quick Mode
                subBuffer = writePart(buffer, subBuffer, length, &subLen, FIRST_TWENTY_PRECENTS); // get first 20%
                if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                {
                    printf("%s - infected! (first 20%%)\n", name);
                    fprintf(logFile, "%s - infected! (first 20%%)\n", name);
                }
                else {
                    free(subBuffer);
                    subBuffer = writePart(buffer, subBuffer, length, &subLen, LAST_TWENTY_PRECENTS); // get last 20%
                    if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                    {

                        printf("%s - Infected! (last 20%%)\n", name);
                        fprintf(logFile, "%s - Infected! (last 20%%)\n", name);
                    }
                    else {
                        subBuffer = writePart(buffer, subBuffer, length, &subLen, MIDDLE_SIXTY_PRECENTS); // get the 60% left in the middle
                        if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                        {
                            printf("%s - Infected!\n", name);
                            fprintf(logFile, "%s - Infected!\n", name);
                        }
                        else {
                            printf("%s - clean\n", name);
                            fprintf(logFile, "%s - Clean\n", name);
                        }
                    }
                }
                free(subBuffer);
            }
            fclose(f);
        }
        else
        {
            printf("No file found\n");
        }
        free(*(filesList + i));
        free(name);
    }
    fclose(logFile);
    free(log);
    free(buffer);
    getchar();
}

/*
This function will write part of the file (beginning, middle or end) to a string
input: source (string) to take the information from, destination (string) to write a part of the source to it,
       length (int) of the source string, a pointer (int*) to store the new length of the destination string and
       part of the file to write from (int) 1,2 or 3: first 20%, 60% in the middle and last 20% accordingly
output: string containing the desired part of the source string
*/
char* writePart(char *src, char *dest, int length, int *newLen, int part) {
    int i = 0;
    int percentedLength = 0;
    int count = 0;
    percentedLength = (int)(length / 5); // this len is 20% of the entire file's length

    if (part == FIRST_TWENTY_PRECENTS) // return beginning
    {
        dest = (char*)malloc(sizeof(char) * percentedLength);
        *newLen = percentedLength;

        for (i = 0; i < percentedLength; i++)
        {
            *(dest + i) = *(src + i);
        }
    }
    else if (part == MIDDLE_SIXTY_PRECENTS)  // return middle
    {
        // allocate space for the middle: The entire file size minus 20% from the start and 20% from the end
        dest = (char*)malloc(sizeof(char) * (length - 2 * percentedLength));
        *newLen = length - 2 * percentedLength;

        for (i = percentedLength; i < length - percentedLength; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
    }
    else if (part == LAST_TWENTY_PRECENTS) // return end
    {
        dest = (char*)malloc(sizeof(char) * percentedLength);
        *newLen = percentedLength;

        for (i = length - percentedLength; i < length; i++)
        {
            *(dest + count) = *(src + i);
            count++;
        }
    }
    return dest;
}

/*
function that finds the length of a file
input: file (FILE *)
output: the file's length (long)
*/
long findLenOfFile(FILE * file)
{
    long length = 0;
    fseek(file, 0, SEEK_END);
    length = ftell(file);
    fseek(file, 0, SEEK_SET);
    return length;
}

/*
function checks whether a file contains the virusSignature. It iterates over each letter of the file and checks
if it is the same as the first letter in the virusSignature. If it is, it checks the rest of the characters and
returns True if a match is found. if not it continues the same process until the end of the file is reached.
input: The virusSignature (string), a buffer with the content of a file (string), the signature's length (int)
       and the buffer's length (int)
output: True if signature is in file, False otherwise
*/
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen)
{
    int found = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < bufferLen - (sigLen - 1); i++) {
        if (*(buffer + i) == *virusSignature) // check if a letter is the same as first letter in virusSignature
        {
            found = TRUE;
            // check if the rest of the letters match the signature and stop if one doesn't
            for (j = 1; (j < sigLen) && found; j++) {
                if (*(buffer + (i + j)) != *(virusSignature + j)) {
                    found = FALSE;
                }
            }
            if (found) {
                return TRUE; // if we got a match, return true!
            }
        }
    }
    return FALSE;
}
</code>```

答:
The realloc call in writeFilesFromFolder has a bug.

It is:

```<code>filesList = (char **) realloc(filesList, sizeof(filesList) + sizeof(char *) + 4);
</code>```

Notice that the space allocated for filesList is constant. It does not grow as new elements are added, so you have undefined behavior.

This is not a memory leak as the tool detected. A memory leak means that you fail to free a pointer that goes out of scope.

Rather, you're storing data beyond the end of the area you've allocated, trashing whatever is there, which is probably the [hidden] chain pointer area that malloc et. al. use to keep track of allocations.

I'm not sure how either of the sizeof factor in, but, filesList is a pointer, so sizeof(filesList) is constant [either 4 on a 32 bit machine or 8 for 64 bit].

The allocated space has to increase in proportion to i.

Here is a refactored version of that function that fixes the bug along with some simplification and cleanup:

BTW, don't cast malloc: Do I cast the result of malloc?

Also, note that sizeof(char) is [by definition] always 1 regardless of how many bits a char actually has for a given architecture. So, remove any sizeof(char) *

Instead of (e.g.):

```<code>*(filesList + i)
</code>```

It's usually simpler/cleaner to do:

```<code>filesList[i]
</code>```

Anyway, here's the code:

```<code>/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char **
writeFilesFromFolder(char *scanFolder, char **filesList, int *len)
{
    DIR *d = 0;

    struct dirent *dir;

    d = opendir(scanFolder);
    int i = -FIRST_TWO_FILES;

    if (d) {
        while ((dir = readdir(d)) != NULL) {
            if (i >= 0) {
                filesList = realloc(filesList,sizeof(*filesList) * (i + 1));
                filesList[i] = strdup(dir->d_name);
            }
            i++;
        }
        closedir(d);
    }

    *len = i;           // first two names is "." and ".."

    return filesList;
}
</code>```

UPDATE:

Okay, you do have memory leaks. And, I've coded up detection and a fix.

Primarily, what you are doing is passing down a buffer pointer to a function (e.g. readFile or writePart) as an argument (e.g. dest).

Then, you are doing:

```<code>dest = malloc(percentedLength);
</code>```

This leaks the previous value of dest.

Normally, functions that allocate a buffer and return it do not take it as an argument. But, after analyzing your code, replacing the malloc with a realloc prevents the leak.

I had to do a complete code review to find this. And, I did several simplifications and cleanups along the way to try to understand your code and isolate possible further issues.

I replaced your allocation/concatenation of filenames with a new function filejoin.

I replaced the other malloc calls with a macro: ALLOCME that detects the memory leaks before they happen. This works in conjunction with the [new] FREEME macro that replaces the free calls.

The default mode is to detect the leak and abort. If you give the program a -f option, it will fix the problem. After you analyze and understand what happened, you can change the default to the "fix" mode.

Where possible, I left your original code under #if 0

A few more style tips:

Keep lines to <= 80 chars.

Don't use "sidebar" comments, particularly on if clauses (e.g.):

```<code>if (...) { // process the file
</code>```

Replace with:

```<code>// process the file
if (...) {
</code>```

Don't replicate code. When you are replicating similar code [as in where I replaced the code with filejoin], this indicates a good place to write a modular function

Anyway, here's the refactored and fixed code:

```<code>#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <assert.h>

#define FALSE 0
#define TRUE (! FALSE)
#define FIRST_TWO_FILES 2
#define FIRST_TWENTY_PRECENTS 1
#define MIDDLE_SIXTY_PRECENTS 2
#define LAST_TWENTY_PRECENTS 3

#define ALLOCME(_ptr,_len) \
    do { \
        _ptr = allocme(_ptr,_len,__FUNCTION__,__LINE__); \
    } while (0)

#define FREEME(_ptr) \
    do { \
        if (_ptr != NULL) \
            free(_ptr); \
        _ptr = NULL; \
    } while (0)

void
sysfault(const char *fmt,...)
{
    va_list ap;

    va_start(ap,fmt);
    vfprintf(stderr,fmt,ap);
    va_end(ap);

    exit(1);
}

long findLenOfFile(FILE * file);
char *readFile(FILE * f, char *dest, long len);
char menu(const char *scanFolder, const char *virusSignature);
char **writeFilesFromFolder(const char *scanFolder, char **filesList, int *len);
char *writePart(char *src, char *dest, int length, int *newLen, int part);
int findSignature(char *virusSignature, char *buffer, int sigLen,
int bufferLen);
void scanFiles(const char *scanFolder, char **filesList, int amountOfFiles,
char *virusSignature, long virusLength, char option);

int opt_fixme = 0;

// allocme -- guarded allocation
void *
allocme(void *ptr,size_t len,const char *fnc,int lno)
{

    if (! opt_fixme) {
        if (ptr != NULL)
            sysfault("allocme: leaking ptr=%p len=%zu (from %s at line %d)\n",
                ptr,len,fnc,lno);
    }

    ptr = realloc(ptr,len);

    if (ptr == NULL)
        sysfault("allocme: realloc failure\n");

    return ptr;
}

#ifdef __linux__
const char *slash = "/";
#else
const char *slash = "\\";
#endif

// filejoin -- create filename from directory and file tail
char *
filejoin(const char *dir,const char *tail)
{
    size_t len;
    char *file;

    len = 0;
    len += strlen(dir);
    len += strlen(slash);
    len += strlen(tail);
    len += 1;

    file = malloc(len);
    if (file == NULL)
        sysfault("filejoin: unable to alloc -- %s\n",strerror(errno));

    *file = 0;

    strcat(file,dir);
    strcat(file,slash);
    strcat(file,tail);

    return file;
}

int
main(int argc, char **argv)
{
#if 0
    char *log = malloc(strlen(argv[1]) + strlen("\\Log.txt") + 4);
#else
    char *log;
#endif

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        case 'f':
            opt_fixme = ! opt_fixme;
            break;
        }
    }

    if (argc != 2)
        sysfault("usage: <folder_to_scan> <virus_signature_file>\n");

    const char *topdir = argv[0];
    const char *sigfile = argv[1];

    FILE *virusSignatureFile = fopen(sigfile, "rb");
    if (virusSignatureFile == NULL)
        sysfault("main: unable to open '%s' -- %s\n",sigfile,strerror(errno));

    long virusLength = 0;
#if 0
    char **filesList = malloc(0);
#else
    char **filesList = NULL;
#endif
    char *virusSignature = NULL;
    int amountOfFiles = 0;
    char option = 0;

    virusLength = findLenOfFile(virusSignatureFile);

    // get the virusSignature as a string and write the files to check into the
    // filesList
    virusSignature = readFile(virusSignatureFile, virusSignature, virusLength);

#if 1
    fclose(virusSignatureFile);
#endif

    filesList = writeFilesFromFolder(topdir, filesList, &amountOfFiles);

    // create log file
#if 0
    strcpy(log, "");
    strcat(log, argv[1]);
    strcat(log, "\\Log.txt");
#else
    log = filejoin(topdir,"Log.txt");
#endif
    FILE *logFile = fopen(log, "w");

    fprintf(logFile, "Anti-virus began! Welcome!\n\n"
        "Folder to scan:\n%s\n"
        "Virus signature:\n%s\n\n"
        "Scanning option:\n", topdir, sigfile);

    // get scanning option (normal or quick) and continue accordingly
    option = menu(topdir, sigfile);
    if (option == '0') {
        fprintf(logFile, "Normal Scan\n\n");
    }
    else {
        fprintf(logFile, "Quick Scan\n\n");
    }
    fprintf(logFile, "Results:\n");
    fclose(logFile);

    // initiate scan
    scanFiles(topdir, filesList, amountOfFiles, virusSignature, virusLength,
        option);

#if 0
    fclose(virusSignatureFile);
#endif

    FREEME(log);
    FREEME(filesList);
    FREEME(virusSignature);

#ifndef __linux__
    getchar();
#endif

    return 0;
}

/*
This function will print the scanning folder path and signature path, also
will print the option menu to the user of quick or normal scan,
after that function will return user option(0, or other key)
input: scanFolder path (string), virus signature path (also string)
output: user option (char: '0', or other key)
*/
char
menu(const char *scanFolder, const char *virusSignature)
{
    char userOption = '\0';

    printf("Welcome to my Virus Scan!\n\n"
        "Folder to scan: %s\n"
        "Virus signature: %s\n\n"
        "Press 0 for a norman scan or any other key for a quick scan: ",
        scanFolder, virusSignature);
    userOption = getchar();
    printf("Scanning began...\nThis process may take several minutes...\n\n");
    return userOption;
}

/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char **
writeFilesFromFolder(const char *scanFolder, char **filesList, int *len)
{
    DIR *d = 0;

    struct dirent *dir;

    d = opendir(scanFolder);
    int i = -FIRST_TWO_FILES;

    if (d) {
        while ((dir = readdir(d)) != NULL) {
            if (i >= 0) {
                filesList = realloc(filesList,sizeof(*filesList) * (i + 1));
                filesList[i] = strdup(dir->d_name);
            }
            i++;
        }
        closedir(d);
    }

    // first two names is "." and ".."
    *len = i;

    return filesList;
}

/*
This function will read the contents of a file into a string
input: a file (FILE *) to read from
output: char* with the contents of the file
*/
char *
readFile(FILE * f, char *dest, long len)
{

// NOTE/BUG: this does _not_ free the prior value -- memory leak!
    ALLOCME(dest,len);

    fread(dest, 1, len, f);

    return dest;
}

void
scanFiles(const char *scanFolder, char **filesList, int amountOfFiles,
char *virusSignature, long virusLength, char option)
{
#if 0
    char *log = malloc(strlen(scanFolder) + strlen("\\Log.txt") + 1);
#else
    char *log;
#endif
#if 0
    char *buffer = malloc(0);
#else
    char *buffer = NULL;
#endif
    char *subBuffer = NULL;
    long length = 0;
    char *name = NULL;
    int subLen = 0;
    int i = 0;
    FILE *f;

    // reopen log file and append to it
#if 0
    strcpy(log, "");
    strcat(log, scanFolder);
    strcat(log, "\\Log.txt");
#else
    log = filejoin(scanFolder,"Log.txt");
#endif
    FILE *logFile = fopen(log, "a");

    // iterate over each file
    for (i = 0; i < amountOfFiles; i++) {
#if 0
        name = malloc(strlen(scanFolder) + 1 + strlen(slash) + strlen(*(filesList + i)) + 20);
#endif

        // open current file
#if 0
        strcpy(name, "");
        strcat(name, scanFolder);
        strcat(name, slash);
        strcat(name, *(filesList + i));
#else
        name = filejoin(scanFolder,filesList[i]);
#endif
        f = fopen(name, "rb");

        length = findLenOfFile(f);

        // if file can be accessed
        if (f != NULL) {
            buffer = readFile(f, buffer, length);

            // Normal Mode
            if (option == '0') {
                if (findSignature(virusSignature, buffer, virusLength, length)) {
                    printf("%s - Infected!\n", name);
                    fprintf(logFile, "%s - Infected!\n", name);
                }
                else {
                    printf("%s - Clean\n", name);
                    fprintf(logFile, "%s - Clean\n", name);
                }
            }

            // Quick Mode
            else {
                // get first 20%
                subBuffer = writePart(buffer, subBuffer, length, &subLen,
                    FIRST_TWENTY_PRECENTS);

                if (findSignature(virusSignature, subBuffer, virusLength,
                    subLen)) {
                    printf("%s - infected! (first 20%%)\n", name);
                    fprintf(logFile, "%s - infected! (first 20%%)\n", name);
                }

                else {
                    FREEME(subBuffer);

                    // get last 20%
                    subBuffer = writePart(buffer, subBuffer, length, &subLen,
                        LAST_TWENTY_PRECENTS);

                    if (findSignature(virusSignature, subBuffer, virusLength,
                        subLen)) {
                        printf("%s - Infected! (last 20%%)\n", name);
                        fprintf(logFile, "%s - Infected! (last 20%%)\n", name);
                    }

                    else {
                        // get the 60% left in the middle
                        subBuffer = writePart(buffer, subBuffer, length,
                            &subLen, MIDDLE_SIXTY_PRECENTS);

                        if (findSignature(virusSignature, subBuffer,
                            virusLength, subLen)) {
                            printf("%s - Infected!\n", name);
                            fprintf(logFile, "%s - Infected!\n", name);
                        }

                        else {
                            printf("%s - clean\n", name);
                            fprintf(logFile, "%s - Clean\n", name);
                        }
                    }
                }
                FREEME(subBuffer);
            }
            fclose(f);
        }
        else {
            printf("No file found\n");
        }

        FREEME(filesList[i]);
        FREEME(name);
    }

    fclose(logFile);
    FREEME(log);
    FREEME(buffer);

    getchar();
}

/*
This function will write part of the file (beginning, middle or end) to a string
input: source (string) to take the information from, destination (string) to
write a part of the source to it, length (int) of the source string, a pointer
(int*) to store the new length of the destination string and part of the file
to write from (int) 1,2 or 3: first 20%, 60% in the middle and last 20%
accordingly
output: string containing the desired part of the source string
*/
char *
writePart(char *src, char *dest, int length, int *newLen, int part)
{
    int i = 0;
    int percentedLength = 0;
    int count = 0;

    // this len is 20% of the entire file's length
    percentedLength = (int) (length / 5);

// NOTE/BUG: this does _not_ free the prior value -- memory leak!

    switch (part) {
    case FIRST_TWENTY_PRECENTS:  // return beginning
        ALLOCME(dest,percentedLength);
        *newLen = percentedLength;

        for (i = 0; i < percentedLength; i++) {
            *(dest + i) = *(src + i);
        }
        break;

    case MIDDLE_SIXTY_PRECENTS:  // return middle
        // allocate space for the middle: The entire file size minus 20% from
        // the start and 20% from the end
        ALLOCME(dest,length - 2 * percentedLength);
        *newLen = length - 2 * percentedLength;

        for (i = percentedLength; i < length - percentedLength; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
        break;

    case LAST_TWENTY_PRECENTS:  // return end
        ALLOCME(dest,percentedLength);
        *newLen = percentedLength;

        for (i = length - percentedLength; i < length; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
        break;
    }

    return dest;
}

/*
function that finds the length of a file
input: file (FILE *)
output: the file's length (long)
*/
long
findLenOfFile(FILE * file)
{
    long length = 0;

    fseek(file, 0, SEEK_END);
    length = ftell(file);
    fseek(file, 0, SEEK_SET);

    return length;
}

/*
function checks whether a file contains the virusSignature.

It iterates over each letter of the file and checks if it is the same as the
first letter in the virusSignature.
If it is, it checks the rest of the characters and returns True if a match is
found.
if not it continues the same process until the end of the file is reached.

input: The virusSignature (string), a buffer with the content of a file
       (string), the signature's length (int)
       and the buffer's length (int)

output: True if signature is in file, False otherwise
*/
int
findSignature(char *virusSignature, char *buffer, int sigLen, int bufferLen)
{
    int found = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < bufferLen - (sigLen - 1); i++) {
        // check if a letter is the same as first letter in virusSignature
        if (*(buffer + i) == *virusSignature)
        {
            found = TRUE;

            // check if the rest of the letters match the signature and stop
            // if one doesn't
            for (j = 1; (j < sigLen) && found; j++) {
                if (*(buffer + (i + j)) != *(virusSignature + j)) {
                    found = FALSE;
                }
            }

            // if we got a match, return true!
            if (found) {
                return TRUE;
            }
        }
    }

    return FALSE;
}
</code>```

Title: Cant find memory leak in C

Body:
I've been sitting for hours checking this code after I found out there's a memory leak/error somewhere
Where is that leak? How can it be fixed?
here is Dr.Memory report:

Dr. Memory version 2.3.0
         Running "C:\Users\Beni\source\repos\Magshimim_EX8\Debug\Magshimim_EX8.exe"
         Using system call file C:\Users\Beni\AppData\Roaming\Dr. Memory\symcache\syscalls_wow64.txt

         Error #1: UNADDRESSABLE ACCESS: reading 1 byte(s)
         replace_strlen
             d:\drmemory_package\drmemory\replace.c(412):
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         Magshimim_EX8.exe!?
             ??:0
         KERNEL32.dll!BaseThreadInitThunk
             ??:0

         ERRORS FOUND:
               1 unique,     1 total unaddressable access(es)
               0 unique,     0 total uninitialized access(es)
               0 unique,     0 total invalid heap argument(s)
               0 unique,     0 total GDI usage error(s)
               0 unique,     0 total handle leak(s)
               0 unique,     0 total warning(s)
               0 unique,     0 total,      0 byte(s) of leak(s)
               0 unique,     0 total,      0 byte(s) of possible leak(s)
         Details: C:\Users\Beni\AppData\Roaming\Dr. Memory\DrMemory-Magshimim_EX8.exe.5208.000\results.txt
         WARNING: application exited with abnormal code 0xc0000005

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>

#define FALSE 0
#define TRUE !FALSE
#define FIRST_TWO_FILES 2
#define FIRST_TWENTY_PRECENTS 1
#define MIDDLE_SIXTY_PRECENTS 2
#define LAST_TWENTY_PRECENTS 3

long findLenOfFile(FILE * file);
char* readFile(FILE* f, char* dest, long len);
char menu(char* scanFolder, char* virusSignature);
char** writeFilesFromFolder(char* scanFolder, char ** filesList, int* len);
char* writePart(char* src, char* dest, int length, int* newLen, int part);
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen);
void scanFiles(char* scanFolder, char** filesList, int amountOfFiles, char* virusSignature, long virusLength, char option);

int main(int argc, char* argv[])
{
    char* log = malloc(sizeof(char)*strlen(argv[1]) + sizeof(char)*strlen("\\Log.txt") + 4);
    FILE* virusSignatureFile = fopen(argv[2], "rb");
    long virusLength = 0;
    char** filesList = (char**)malloc(sizeof(char) * 0);
    char* virusSignature = 0;
    int amountOfFiles = 0;
    char option = 0;
    int i = 0;

    virusLength = findLenOfFile(virusSignatureFile);

    // get the virusSignature as a string and write the files to check into the filesList
    virusSignature = readFile(virusSignatureFile, virusSignature, virusLength);
    filesList = writeFilesFromFolder(argv[1], filesList, &amountOfFiles);

    // create log file
    strcpy(log, "");
    strcat(log, argv[1]);
    strcat(log, "\\Log.txt");
    FILE * logFile = fopen(log, "w");
    fprintf(logFile, "Anti-virus began! Welcome!\n\nFolder to scan:\n%s\nVirus signature:\n%s\n\nScanning option:\n", argv[1], argv[2]);

    // get scanning option (normal or quick) and continue accordingly
    option = menu(argv[1], argv[2]);
    if (option == '0') {
        fprintf(logFile, "Normal Scan\n\n");
    }
    else {
        fprintf(logFile, "Quick Scan\n\n");
    }
    fprintf(logFile, "Results:\n");
    fclose(logFile);

    // initiate scan
    scanFiles(argv[1], filesList, amountOfFiles, virusSignature, virusLength, option);

    fclose(virusSignatureFile);
    free(log);
    free(filesList);
    free(virusSignature);
    getchar();
    return 0;
}

/*
This function will print the scanning folder path and signature path, also will print the option menu to the user of quick or normal scan,
after that function will return user option(0, or other key)
input: scanFolder path (string), virus signature path (also string)
output: user option (char: '0', or other key)
*/
char menu(char * scanFolder, char * virusSignature)
{
    char userOption = '\0';
    printf("Welcome to my Virus Scan!\n\nFolder to scan: %s\nVirus signature: %s\n\nPress 0 for a norman scan or any other key for a quick scan: ", scanFolder, virusSignature);
    userOption = getchar();
    printf("Scanning began...\nThis process may take several minutes...\n\n");
    return userOption;
}

/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char** writeFilesFromFolder(char * scanFolder, char ** filesList, int* len)
{
    DIR *d = 0;

    struct dirent *dir;
    d = opendir(scanFolder);
    int i = 0;

    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if (i > 1)
            {
                filesList = (char**)realloc(filesList, sizeof(filesList) + sizeof(char*) + 4);
                *(filesList + (i - FIRST_TWO_FILES)) = (char*)malloc(sizeof(char) * strlen(dir->d_name) + 1);
                strcpy(*(filesList + (i - FIRST_TWO_FILES)), (dir->d_name));
            }
            i++;
        }
        closedir(d);
    }
    *len = i - FIRST_TWO_FILES; //first two names is "." and ".."
    return filesList;
}

/*
This function will read the contents of a file into a string
input: a file (FILE *) to read from
output: char* with the contents of the file
*/
char* readFile(FILE* f, char * dest, long len)
{
    dest = (char*)malloc(sizeof(char) * len);
    fread(dest, 1, len, f);
    return dest;
}

void scanFiles(char * scanFolder, char ** filesList, int amountOfFiles, char * virusSignature, long virusLength, char option)
{
    char* log = malloc(sizeof(char)*strlen(scanFolder) + sizeof(char)*strlen("\\Log.txt") + 1);
    char * buffer = (char*)malloc(sizeof(char) * 0);
    char* subBuffer = 0;
    char* slash = "\\";
    long length = 0;
    char* name = 0;
    int subLen = 0;
    int i = 0;
    FILE * f;

    // reopen log file and append to it
    strcpy(log, "");
    strcat(log, scanFolder);
    strcat(log, "\\Log.txt");
    FILE * logFile = fopen(log, "a");

    // iterate over each file
    for (i = 0; i < amountOfFiles; i++)
    {
        name = (char*)malloc(sizeof(char) * strlen(scanFolder) + 1 + sizeof(char) * strlen(slash) + sizeof(char) * strlen(*(filesList + i)) + 20);

        // open current file
        strcpy(name, "");
        strcat(name, scanFolder);
        strcat(name, slash);
        strcat(name, *(filesList + i));
        f = fopen(name, "rb");

        length = findLenOfFile(f);

        if (f != NULL) // if file can be accessed
        {
            buffer = readFile(f, buffer, length);
            if (option == '0') { // Normal Mode
                if (findSignature(virusSignature, buffer, virusLength, length))
                {
                    printf("%s - Infected!\n", name);
                    fprintf(logFile, "%s - Infected!\n", name);
                }
                else
                {
                    printf("%s - Clean\n", name);
                    fprintf(logFile, "%s - Clean\n", name);
                }
            }
            else { // Quick Mode
                subBuffer = writePart(buffer, subBuffer, length, &subLen, FIRST_TWENTY_PRECENTS); // get first 20%
                if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                {
                    printf("%s - infected! (first 20%%)\n", name);
                    fprintf(logFile, "%s - infected! (first 20%%)\n", name);
                }
                else {
                    free(subBuffer);
                    subBuffer = writePart(buffer, subBuffer, length, &subLen, LAST_TWENTY_PRECENTS); // get last 20%
                    if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                    {

                        printf("%s - Infected! (last 20%%)\n", name);
                        fprintf(logFile, "%s - Infected! (last 20%%)\n", name);
                    }
                    else {
                        subBuffer = writePart(buffer, subBuffer, length, &subLen, MIDDLE_SIXTY_PRECENTS); // get the 60% left in the middle
                        if (findSignature(virusSignature, subBuffer, virusLength, subLen))
                        {
                            printf("%s - Infected!\n", name);
                            fprintf(logFile, "%s - Infected!\n", name);
                        }
                        else {
                            printf("%s - clean\n", name);
                            fprintf(logFile, "%s - Clean\n", name);
                        }
                    }
                }
                free(subBuffer);
            }
            fclose(f);
        }
        else
        {
            printf("No file found\n");
        }
        free(*(filesList + i));
        free(name);
    }
    fclose(logFile);
    free(log);
    free(buffer);
    getchar();
}

/*
This function will write part of the file (beginning, middle or end) to a string
input: source (string) to take the information from, destination (string) to write a part of the source to it,
       length (int) of the source string, a pointer (int*) to store the new length of the destination string and
       part of the file to write from (int) 1,2 or 3: first 20%, 60% in the middle and last 20% accordingly
output: string containing the desired part of the source string
*/
char* writePart(char *src, char *dest, int length, int *newLen, int part) {
    int i = 0;
    int percentedLength = 0;
    int count = 0;
    percentedLength = (int)(length / 5); // this len is 20% of the entire file's length

    if (part == FIRST_TWENTY_PRECENTS) // return beginning
    {
        dest = (char*)malloc(sizeof(char) * percentedLength);
        *newLen = percentedLength;

        for (i = 0; i < percentedLength; i++)
        {
            *(dest + i) = *(src + i);
        }
    }
    else if (part == MIDDLE_SIXTY_PRECENTS)  // return middle
    {
        // allocate space for the middle: The entire file size minus 20% from the start and 20% from the end
        dest = (char*)malloc(sizeof(char) * (length - 2 * percentedLength));
        *newLen = length - 2 * percentedLength;

        for (i = percentedLength; i < length - percentedLength; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
    }
    else if (part == LAST_TWENTY_PRECENTS) // return end
    {
        dest = (char*)malloc(sizeof(char) * percentedLength);
        *newLen = percentedLength;

        for (i = length - percentedLength; i < length; i++)
        {
            *(dest + count) = *(src + i);
            count++;
        }
    }
    return dest;
}

/*
function that finds the length of a file
input: file (FILE *)
output: the file's length (long)
*/
long findLenOfFile(FILE * file)
{
    long length = 0;
    fseek(file, 0, SEEK_END);
    length = ftell(file);
    fseek(file, 0, SEEK_SET);
    return length;
}

/*
function checks whether a file contains the virusSignature. It iterates over each letter of the file and checks
if it is the same as the first letter in the virusSignature. If it is, it checks the rest of the characters and
returns True if a match is found. if not it continues the same process until the end of the file is reached.
input: The virusSignature (string), a buffer with the content of a file (string), the signature's length (int)
       and the buffer's length (int)
output: True if signature is in file, False otherwise
*/
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen)
{
    int found = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < bufferLen - (sigLen - 1); i++) {
        if (*(buffer + i) == *virusSignature) // check if a letter is the same as first letter in virusSignature
        {
            found = TRUE;
            // check if the rest of the letters match the signature and stop if one doesn't
            for (j = 1; (j < sigLen) && found; j++) {
                if (*(buffer + (i + j)) != *(virusSignature + j)) {
                    found = FALSE;
                }
            }
            if (found) {
                return TRUE; // if we got a match, return true!
            }
        }
    }
    return FALSE;
}

Body:
The realloc call in writeFilesFromFolder has a bug.

It is:

filesList = (char **) realloc(filesList, sizeof(filesList) + sizeof(char *) + 4);

Notice that the space allocated for filesList is constant. It does not grow as new elements are added, so you have undefined behavior.

This is not a memory leak as the tool detected. A memory leak means that you fail to free a pointer that goes out of scope.

Rather, you're storing data beyond the end of the area you've allocated, trashing whatever is there, which is probably the [hidden] chain pointer area that malloc et. al. use to keep track of allocations.

I'm not sure how either of the sizeof factor in, but, filesList is a pointer, so sizeof(filesList) is constant [either 4 on a 32 bit machine or 8 for 64 bit].

The allocated space has to increase in proportion to i.

Here is a refactored version of that function that fixes the bug along with some simplification and cleanup:

BTW, don't cast malloc: Do I cast the result of malloc?

Also, note that sizeof(char) is [by definition] always 1 regardless of how many bits a char actually has for a given architecture. So, remove any sizeof(char) *

Instead of (e.g.):

*(filesList + i)

It's usually simpler/cleaner to do:

filesList[i]

Anyway, here's the code:

/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char **
writeFilesFromFolder(char *scanFolder, char **filesList, int *len)
{
    DIR *d = 0;

    struct dirent *dir;

    d = opendir(scanFolder);
    int i = -FIRST_TWO_FILES;

    if (d) {
        while ((dir = readdir(d)) != NULL) {
            if (i >= 0) {
                filesList = realloc(filesList,sizeof(*filesList) * (i + 1));
                filesList[i] = strdup(dir->d_name);
            }
            i++;
        }
        closedir(d);
    }

    *len = i;           // first two names is "." and ".."

    return filesList;
}

UPDATE:

Okay, you do have memory leaks. And, I've coded up detection and a fix.

Primarily, what you are doing is passing down a buffer pointer to a function (e.g. readFile or writePart) as an argument (e.g. dest).

Then, you are doing:

dest = malloc(percentedLength);

This leaks the previous value of dest.

Normally, functions that allocate a buffer and return it do not take it as an argument. But, after analyzing your code, replacing the malloc with a realloc prevents the leak.

I had to do a complete code review to find this. And, I did several simplifications and cleanups along the way to try to understand your code and isolate possible further issues.

I replaced your allocation/concatenation of filenames with a new function filejoin.

I replaced the other malloc calls with a macro: ALLOCME that detects the memory leaks before they happen. This works in conjunction with the [new] FREEME macro that replaces the free calls.

The default mode is to detect the leak and abort. If you give the program a -f option, it will fix the problem. After you analyze and understand what happened, you can change the default to the "fix" mode.

Where possible, I left your original code under #if 0

A few more style tips:

Keep lines to <= 80 chars.

Don't use "sidebar" comments, particularly on if clauses (e.g.):

if (...) { // process the file

Replace with:

// process the file
if (...) {

Don't replicate code. When you are replicating similar code [as in where I replaced the code with filejoin], this indicates a good place to write a modular function

Anyway, here's the refactored and fixed code:

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <assert.h>

#define FALSE 0
#define TRUE (! FALSE)
#define FIRST_TWO_FILES 2
#define FIRST_TWENTY_PRECENTS 1
#define MIDDLE_SIXTY_PRECENTS 2
#define LAST_TWENTY_PRECENTS 3

#define ALLOCME(_ptr,_len) \
    do { \
        _ptr = allocme(_ptr,_len,__FUNCTION__,__LINE__); \
    } while (0)

#define FREEME(_ptr) \
    do { \
        if (_ptr != NULL) \
            free(_ptr); \
        _ptr = NULL; \
    } while (0)

void
sysfault(const char *fmt,...)
{
    va_list ap;

    va_start(ap,fmt);
    vfprintf(stderr,fmt,ap);
    va_end(ap);

    exit(1);
}

long findLenOfFile(FILE * file);
char *readFile(FILE * f, char *dest, long len);
char menu(const char *scanFolder, const char *virusSignature);
char **writeFilesFromFolder(const char *scanFolder, char **filesList, int *len);
char *writePart(char *src, char *dest, int length, int *newLen, int part);
int findSignature(char *virusSignature, char *buffer, int sigLen,
int bufferLen);
void scanFiles(const char *scanFolder, char **filesList, int amountOfFiles,
char *virusSignature, long virusLength, char option);

int opt_fixme = 0;

// allocme -- guarded allocation
void *
allocme(void *ptr,size_t len,const char *fnc,int lno)
{

    if (! opt_fixme) {
        if (ptr != NULL)
            sysfault("allocme: leaking ptr=%p len=%zu (from %s at line %d)\n",
                ptr,len,fnc,lno);
    }

    ptr = realloc(ptr,len);

    if (ptr == NULL)
        sysfault("allocme: realloc failure\n");

    return ptr;
}

#ifdef __linux__
const char *slash = "/";
#else
const char *slash = "\\";
#endif

// filejoin -- create filename from directory and file tail
char *
filejoin(const char *dir,const char *tail)
{
    size_t len;
    char *file;

    len = 0;
    len += strlen(dir);
    len += strlen(slash);
    len += strlen(tail);
    len += 1;

    file = malloc(len);
    if (file == NULL)
        sysfault("filejoin: unable to alloc -- %s\n",strerror(errno));

    *file = 0;

    strcat(file,dir);
    strcat(file,slash);
    strcat(file,tail);

    return file;
}

int
main(int argc, char **argv)
{
#if 0
    char *log = malloc(strlen(argv[1]) + strlen("\\Log.txt") + 4);
#else
    char *log;
#endif

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        case 'f':
            opt_fixme = ! opt_fixme;
            break;
        }
    }

    if (argc != 2)
        sysfault("usage: <folder_to_scan> <virus_signature_file>\n");

    const char *topdir = argv[0];
    const char *sigfile = argv[1];

    FILE *virusSignatureFile = fopen(sigfile, "rb");
    if (virusSignatureFile == NULL)
        sysfault("main: unable to open '%s' -- %s\n",sigfile,strerror(errno));

    long virusLength = 0;
#if 0
    char **filesList = malloc(0);
#else
    char **filesList = NULL;
#endif
    char *virusSignature = NULL;
    int amountOfFiles = 0;
    char option = 0;

    virusLength = findLenOfFile(virusSignatureFile);

    // get the virusSignature as a string and write the files to check into the
    // filesList
    virusSignature = readFile(virusSignatureFile, virusSignature, virusLength);

#if 1
    fclose(virusSignatureFile);
#endif

    filesList = writeFilesFromFolder(topdir, filesList, &amountOfFiles);

    // create log file
#if 0
    strcpy(log, "");
    strcat(log, argv[1]);
    strcat(log, "\\Log.txt");
#else
    log = filejoin(topdir,"Log.txt");
#endif
    FILE *logFile = fopen(log, "w");

    fprintf(logFile, "Anti-virus began! Welcome!\n\n"
        "Folder to scan:\n%s\n"
        "Virus signature:\n%s\n\n"
        "Scanning option:\n", topdir, sigfile);

    // get scanning option (normal or quick) and continue accordingly
    option = menu(topdir, sigfile);
    if (option == '0') {
        fprintf(logFile, "Normal Scan\n\n");
    }
    else {
        fprintf(logFile, "Quick Scan\n\n");
    }
    fprintf(logFile, "Results:\n");
    fclose(logFile);

    // initiate scan
    scanFiles(topdir, filesList, amountOfFiles, virusSignature, virusLength,
        option);

#if 0
    fclose(virusSignatureFile);
#endif

    FREEME(log);
    FREEME(filesList);
    FREEME(virusSignature);

#ifndef __linux__
    getchar();
#endif

    return 0;
}

/*
This function will print the scanning folder path and signature path, also
will print the option menu to the user of quick or normal scan,
after that function will return user option(0, or other key)
input: scanFolder path (string), virus signature path (also string)
output: user option (char: '0', or other key)
*/
char
menu(const char *scanFolder, const char *virusSignature)
{
    char userOption = '\0';

    printf("Welcome to my Virus Scan!\n\n"
        "Folder to scan: %s\n"
        "Virus signature: %s\n\n"
        "Press 0 for a norman scan or any other key for a quick scan: ",
        scanFolder, virusSignature);
    userOption = getchar();
    printf("Scanning began...\nThis process may take several minutes...\n\n");
    return userOption;
}

/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char **
writeFilesFromFolder(const char *scanFolder, char **filesList, int *len)
{
    DIR *d = 0;

    struct dirent *dir;

    d = opendir(scanFolder);
    int i = -FIRST_TWO_FILES;

    if (d) {
        while ((dir = readdir(d)) != NULL) {
            if (i >= 0) {
                filesList = realloc(filesList,sizeof(*filesList) * (i + 1));
                filesList[i] = strdup(dir->d_name);
            }
            i++;
        }
        closedir(d);
    }

    // first two names is "." and ".."
    *len = i;

    return filesList;
}

/*
This function will read the contents of a file into a string
input: a file (FILE *) to read from
output: char* with the contents of the file
*/
char *
readFile(FILE * f, char *dest, long len)
{

// NOTE/BUG: this does _not_ free the prior value -- memory leak!
    ALLOCME(dest,len);

    fread(dest, 1, len, f);

    return dest;
}

void
scanFiles(const char *scanFolder, char **filesList, int amountOfFiles,
char *virusSignature, long virusLength, char option)
{
#if 0
    char *log = malloc(strlen(scanFolder) + strlen("\\Log.txt") + 1);
#else
    char *log;
#endif
#if 0
    char *buffer = malloc(0);
#else
    char *buffer = NULL;
#endif
    char *subBuffer = NULL;
    long length = 0;
    char *name = NULL;
    int subLen = 0;
    int i = 0;
    FILE *f;

    // reopen log file and append to it
#if 0
    strcpy(log, "");
    strcat(log, scanFolder);
    strcat(log, "\\Log.txt");
#else
    log = filejoin(scanFolder,"Log.txt");
#endif
    FILE *logFile = fopen(log, "a");

    // iterate over each file
    for (i = 0; i < amountOfFiles; i++) {
#if 0
        name = malloc(strlen(scanFolder) + 1 + strlen(slash) + strlen(*(filesList + i)) + 20);
#endif

        // open current file
#if 0
        strcpy(name, "");
        strcat(name, scanFolder);
        strcat(name, slash);
        strcat(name, *(filesList + i));
#else
        name = filejoin(scanFolder,filesList[i]);
#endif
        f = fopen(name, "rb");

        length = findLenOfFile(f);

        // if file can be accessed
        if (f != NULL) {
            buffer = readFile(f, buffer, length);

            // Normal Mode
            if (option == '0') {
                if (findSignature(virusSignature, buffer, virusLength, length)) {
                    printf("%s - Infected!\n", name);
                    fprintf(logFile, "%s - Infected!\n", name);
                }
                else {
                    printf("%s - Clean\n", name);
                    fprintf(logFile, "%s - Clean\n", name);
                }
            }

            // Quick Mode
            else {
                // get first 20%
                subBuffer = writePart(buffer, subBuffer, length, &subLen,
                    FIRST_TWENTY_PRECENTS);

                if (findSignature(virusSignature, subBuffer, virusLength,
                    subLen)) {
                    printf("%s - infected! (first 20%%)\n", name);
                    fprintf(logFile, "%s - infected! (first 20%%)\n", name);
                }

                else {
                    FREEME(subBuffer);

                    // get last 20%
                    subBuffer = writePart(buffer, subBuffer, length, &subLen,
                        LAST_TWENTY_PRECENTS);

                    if (findSignature(virusSignature, subBuffer, virusLength,
                        subLen)) {
                        printf("%s - Infected! (last 20%%)\n", name);
                        fprintf(logFile, "%s - Infected! (last 20%%)\n", name);
                    }

                    else {
                        // get the 60% left in the middle
                        subBuffer = writePart(buffer, subBuffer, length,
                            &subLen, MIDDLE_SIXTY_PRECENTS);

                        if (findSignature(virusSignature, subBuffer,
                            virusLength, subLen)) {
                            printf("%s - Infected!\n", name);
                            fprintf(logFile, "%s - Infected!\n", name);
                        }

                        else {
                            printf("%s - clean\n", name);
                            fprintf(logFile, "%s - Clean\n", name);
                        }
                    }
                }
                FREEME(subBuffer);
            }
            fclose(f);
        }
        else {
            printf("No file found\n");
        }

        FREEME(filesList[i]);
        FREEME(name);
    }

    fclose(logFile);
    FREEME(log);
    FREEME(buffer);

    getchar();
}

/*
This function will write part of the file (beginning, middle or end) to a string
input: source (string) to take the information from, destination (string) to
write a part of the source to it, length (int) of the source string, a pointer
(int*) to store the new length of the destination string and part of the file
to write from (int) 1,2 or 3: first 20%, 60% in the middle and last 20%
accordingly
output: string containing the desired part of the source string
*/
char *
writePart(char *src, char *dest, int length, int *newLen, int part)
{
    int i = 0;
    int percentedLength = 0;
    int count = 0;

    // this len is 20% of the entire file's length
    percentedLength = (int) (length / 5);

// NOTE/BUG: this does _not_ free the prior value -- memory leak!

    switch (part) {
    case FIRST_TWENTY_PRECENTS:  // return beginning
        ALLOCME(dest,percentedLength);
        *newLen = percentedLength;

        for (i = 0; i < percentedLength; i++) {
            *(dest + i) = *(src + i);
        }
        break;

    case MIDDLE_SIXTY_PRECENTS:  // return middle
        // allocate space for the middle: The entire file size minus 20% from
        // the start and 20% from the end
        ALLOCME(dest,length - 2 * percentedLength);
        *newLen = length - 2 * percentedLength;

        for (i = percentedLength; i < length - percentedLength; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
        break;

    case LAST_TWENTY_PRECENTS:  // return end
        ALLOCME(dest,percentedLength);
        *newLen = percentedLength;

        for (i = length - percentedLength; i < length; i++) {
            *(dest + count) = *(src + i);
            count++;
        }
        break;
    }

    return dest;
}

/*
function that finds the length of a file
input: file (FILE *)
output: the file's length (long)
*/
long
findLenOfFile(FILE * file)
{
    long length = 0;

    fseek(file, 0, SEEK_END);
    length = ftell(file);
    fseek(file, 0, SEEK_SET);

    return length;
}

/*
function checks whether a file contains the virusSignature.

It iterates over each letter of the file and checks if it is the same as the
first letter in the virusSignature.
If it is, it checks the rest of the characters and returns True if a match is
found.
if not it continues the same process until the end of the file is reached.

input: The virusSignature (string), a buffer with the content of a file
       (string), the signature's length (int)
       and the buffer's length (int)

output: True if signature is in file, False otherwise
*/
int
findSignature(char *virusSignature, char *buffer, int sigLen, int bufferLen)
{
    int found = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < bufferLen - (sigLen - 1); i++) {
        // check if a letter is the same as first letter in virusSignature
        if (*(buffer + i) == *virusSignature)
        {
            found = TRUE;

            // check if the rest of the letters match the signature and stop
            // if one doesn't
            for (j = 1; (j < sigLen) && found; j++) {
                if (*(buffer + (i + j)) != *(virusSignature + j)) {
                    found = FALSE;
                }
            }

            // if we got a match, return true!
            if (found) {
                return TRUE;
            }
        }
    }

    return FALSE;
}


来源: stackexchange

问:
How to convert to datetime even if the column contains strings
I have a dataframe with column date as dtype object.

```<code>id           date         name
1           1/1/2020       A
2           2/1/2020       B
3           2/1/2020
Total      3 Entries      2 Entries
</code>```

I want to convert this date column to pd.datetime. But as it contains a Total it gives an error: dateutil.parser._parser.ParserError: Unknown string format: 3 Entries

How can I tell pandas to change only the date format rows should be changed to datetime ? Actually I just want the month from that date to a new column.
What are my alternatives to achieve this ?

desired result:

```<code>id           date         name          month
1           1/1/2020       A              1
2           2/1/2020       B              1
3           2/1/2020                      1
Total      3 Entries      2 Entries     Nan/0

</code>```

答:
try this, to_datetime with errors=coerce will parse invalid dates & set to NaT.

```<code>df['month'] = pd.to_datetime(df['date'], format="%d/%m/%Y", errors='coerce').dt.month

print(df['month'])
</code>```

output,

```<code>      id       date       name  month
0      1   1/1/2020          A    1.0
1      2   2/1/2020          B    1.0
2      3   2/1/2020       None    1.0
3  Total  3 Entries  2 Entries    NaN
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have a dataframe with column date as dtype object.

id           date         name
1           1/1/2020       A
2           2/1/2020       B
3           2/1/2020
Total      3 Entries      2 Entries

I want to convert this date column to pd.datetime. But as it contains a Total it gives an error: dateutil.parser._parser.ParserError: Unknown string format: 3 Entries

How can I tell pandas to change only the date format rows should be changed to datetime ? Actually I just want the month from that date to a new column.
What are my alternatives to achieve this ?

desired result:

id           date         name          month
1           1/1/2020       A              1
2           2/1/2020       B              1
3           2/1/2020                      1
Total      3 Entries      2 Entries     Nan/0

Body:
try this, to_datetime with errors=coerce will parse invalid dates & set to NaT.

df['month'] = pd.to_datetime(df['date'], format="%d/%m/%Y", errors='coerce').dt.month

print(df['month'])

output,

      id       date       name  month
0      1   1/1/2020          A    1.0
1      2   2/1/2020          B    1.0
2      3   2/1/2020       None    1.0
3  Total  3 Entries  2 Entries    NaN


问:
No 'Access-Control-Allow-Origin' in Spring Boot + Spring Security + CORS
I'm trying CORS with Spring security. So here is my WebSecurityConfigurerAdapter :

```<code>
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login();
    }
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("*"));
        configuration.setAllowedMethods(List.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
</code>```

And here is my WebMvcCofigurer :

```<code>@EnableWebSecurity
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer
{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
    }
}
</code>```

But it gives me
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Current code :
SecurityConfig.java

```<code>import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true,
        prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .disable()//some stackoverflow solution(not accepted) said so
                .csrf()
                .disable()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login();
    }
}
</code>```

WebConfig.java:

```<code>import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebSecurity
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")
                .allowedHeaders("*")
                .allowCredentials(true);
    }

}
</code>```

I tried even a filter(As it crashes when starting, so I removed it)
MyCorsFilter.java

```<code>@Configuration
public class MyCorsFilter {
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedHeader("*");//tried list and all other collection stuff
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);//tried with negative value
        return bean;
    }
}
</code>```

Also tried

```<code>http
.headers()
.addHeaderWriter(
      new StaticHeadersWriter(
            "Access-Control-Allow-Origin",
            "http://localhost:3000"))
</code>```

And here is the OAuth2 configuration :

```<code>@Configuration
public class OAuth2Config {
    @Bean
    @RequestScope
    public GoogleOAuth2 google(OAuth2AuthorizedClientService clientService) {
        Authentication authentication =
                SecurityContextHolder.getContext().getAuthentication();
        String accessToken = null;
        if (authentication.getClass()
                .isAssignableFrom(OAuth2AuthenticationToken.class)) {
            OAuth2AuthenticationToken oauthToken =
                    (OAuth2AuthenticationToken) authentication;
            String clientRegistrationId =
                    oauthToken.getAuthorizedClientRegistrationId();
            if (clientRegistrationId.equals("google")) {
                OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(
                        clientRegistrationId, oauthToken.getName());
                accessToken = client.getAccessToken().getTokenValue();
            }
        }
        return new GoogleOAuth2(accessToken);
    }

}
</code>```

答:
UPDATE:

CORS issue with Google Oauth2 for server side webapps

CORS issue while making an Ajax request for oauth2 access token

When you use the Authorization code grant (OAuth2 for backend apps - &response_type=code), you must redirect the browser to the /auth endpoint - you cannot use XHR for that. The user will be redirected back after authentication.

After redirecting to the /auth endpoint, user needs to see in an address bar that the page is from Google (trusted source) and Google may need to do some more redirects in order to authenticate the user and present the consent page. So using XHR is not possible.

You may use UrlBasedCorsConfigurationSource with CorsFilter as used below. Please comment or remove the other CORS configurations and try with it.

```<code>package com.learning.jhipster.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    jsr250Enabled = true,
    prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CorsFilter corsFilter;

    public SecurityConfig(@Lazy CorsFilter corsFilter) {
        this.corsFilter = corsFilter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
            .disable()//some stackoverflow solution(not accepted) said so
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .oauth2Login();
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("*"));
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
</code>```

Body:
I'm trying CORS with Spring security. So here is my WebSecurityConfigurerAdapter :

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login();
    }
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("*"));
        configuration.setAllowedMethods(List.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

And here is my WebMvcCofigurer :

@EnableWebSecurity
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer
{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
    }
}

But it gives me
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Current code :
SecurityConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true,
        prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .disable()//some stackoverflow solution(not accepted) said so
                .csrf()
                .disable()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login();
    }
}

WebConfig.java:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebSecurity
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")
                .allowedHeaders("*")
                .allowCredentials(true);
    }

}

I tried even a filter(As it crashes when starting, so I removed it)
MyCorsFilter.java

@Configuration
public class MyCorsFilter {
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedHeader("*");//tried list and all other collection stuff
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);//tried with negative value
        return bean;
    }
}

Also tried

http
.headers()
.addHeaderWriter(
      new StaticHeadersWriter(
            "Access-Control-Allow-Origin",
            "http://localhost:3000"))

And here is the OAuth2 configuration :

@Configuration
public class OAuth2Config {
    @Bean
    @RequestScope
    public GoogleOAuth2 google(OAuth2AuthorizedClientService clientService) {
        Authentication authentication =
                SecurityContextHolder.getContext().getAuthentication();
        String accessToken = null;
        if (authentication.getClass()
                .isAssignableFrom(OAuth2AuthenticationToken.class)) {
            OAuth2AuthenticationToken oauthToken =
                    (OAuth2AuthenticationToken) authentication;
            String clientRegistrationId =
                    oauthToken.getAuthorizedClientRegistrationId();
            if (clientRegistrationId.equals("google")) {
                OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(
                        clientRegistrationId, oauthToken.getName());
                accessToken = client.getAccessToken().getTokenValue();
            }
        }
        return new GoogleOAuth2(accessToken);
    }

}

Body:
UPDATE:

CORS issue with Google Oauth2 for server side webapps

CORS issue while making an Ajax request for oauth2 access token

When you use the Authorization code grant (OAuth2 for backend apps - &response_type=code), you must redirect the browser to the /auth endpoint - you cannot use XHR for that. The user will be redirected back after authentication.

After redirecting to the /auth endpoint, user needs to see in an address bar that the page is from Google (trusted source) and Google may need to do some more redirects in order to authenticate the user and present the consent page. So using XHR is not possible.

You may use UrlBasedCorsConfigurationSource with CorsFilter as used below. Please comment or remove the other CORS configurations and try with it.

package com.learning.jhipster.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    jsr250Enabled = true,
    prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CorsFilter corsFilter;

    public SecurityConfig(@Lazy CorsFilter corsFilter) {
        this.corsFilter = corsFilter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
            .disable()//some stackoverflow solution(not accepted) said so
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .oauth2Login();
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("*"));
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}


问:
CSS selector that excludes some child elements
I have this HTML:

```<code><div class="item-cost">
    <a data-passage="Shop" class="link-internal macro-link" tabindex="0" id="Link1">$10 <sup>1</sup></a>
</div>
</code>```

I am writing this testcafe code to get the cost:

```<code>.expect(Selector('.item-cost').nth(0).innerText)
.eql('$1')
</code>```

This fails because the inner text is $11, not $1. The reason it's failing is because the contents of the sup element are included in the inner text. Is there any way I can modify the selector above so that it gives me the inner text without including the sup element? I cannot modify the HTML.

答:
Instead of using innerText, use innerHTML and then use a regexp to remove the trailing ... (including the space before ):

```<code>.expect(Selector('.item-cost').nth(0).innerHTML.replace(/ <sup>.*<\/sup>$/, ''))
.eql('$1')
</code>```

That will give you just the $10.

Body:
I have this HTML:

    $10 1

I am writing this testcafe code to get the cost:

.expect(Selector('.item-cost').nth(0).innerText)
.eql('$1')

This fails because the inner text is $11, not $1. The reason it's failing is because the contents of the sup element are included in the inner text. Is there any way I can modify the selector above so that it gives me the inner text without including the sup element? I cannot modify the HTML.

Body:
Instead of using innerText, use innerHTML and then use a regexp to remove the trailing <sup>...</sup> (including the space before <sup>):

.expect(Selector('.item-cost').nth(0).innerHTML.replace(/ <sup>.*<\/sup>$/, ''))
.eql('$1')

That will give you just the $10.


问:
Model-viewer outline
```<code><!doctype html>
<html>

<head>
    <meta charset="utf-8">

</head>

<body>
    <script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.js"></script>
<script nomodule src="https://unpkg.com/@google/model-viewer/dist/model-viewer-legacy.js"></script>
<!-- Use it like any other HTML element -->
<model-viewer src="shared-assets/models/Astronaut.glb" alt="A 3D model of an astronaut" auto-rotate camera-controls></model-viewer>
</body>

</html>
</code>```

When you click on model viewer the outline appears, I am unable to remove the outline from the model-viewer how would one remove it?

Edit

```<code>/**
 * This is mixin function is designed to be applied to a class that inherits
 * from HTMLElement. It makes it easy for a custom element to coordinate with
 * the :focus-visible polyfill.
 *
 * @param {Function} SuperClass The base class implementation to decorate with
 * implementation that coordinates with the :focus-visible polyfill
 */
export function FocusVisiblePolyfillMixin(SuperClass) {
  var coordinateWithPolyfill = function(instance) {
    // If there is no shadow root, there is no need to coordinate with the
    // polyfill. If we already coordinated with the polyfill, we can skip
    // subsequent invokcations:
    if (
      instance.shadowRoot == null ||
      instance.hasAttribute('data-js-focus-visible')
    ) {
      return;
    }

    // The polyfill might already be loaded. If so, we can apply it to the
    // shadow root immediately:
    if (self.applyFocusVisiblePolyfill) {
      self.applyFocusVisiblePolyfill(instance.shadowRoot);
    } else {
      // Otherwise, wait for the polyfill to be loaded lazily. It might never
      // be loaded, but if it is then we can apply it to the shadow root at
      // the appropriate time by waiting for the ready event:
      self.addEventListener(
        'focus-visible-polyfill-ready',
        function() {
          self.applyFocusVisiblePolyfill(instance.shadowRoot);
        },
        { once: true }
      );
    }
  };

  // IE11 doesn't natively support custom elements or JavaScript class syntax
  // The mixin implementation assumes that the user will take the appropriate
  // steps to support both:
  return class extends SuperClass {
    // Attempt to coordinate with the polyfill when connected to the document:
    connectedCallback() {
      super.connectedCallback && super.connectedCallback();
      coordinateWithPolyfill(this);
    }
  };
}
</code>```

So I added this in file name focus-visible.js

added this to html

```<code><body>
    <!-- The :focus-visible polyfill removes the focus ring for some input types -->
    <script src="focus-visible.js" defer></script>
    <script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.js"></script>
    <script nomodule src="https://unpkg.com/@google/model-viewer/dist/model-viewer-legacy.js"></script>
    <!-- Use it like any other HTML element -->
    <model-viewer src="shared-assets/models/Astronaut.glb" alt="A 3D model of an astronaut" auto-rotate camera-controls>
    </model-viewer>
</body>
</code>```

and this in css :focus-visible polyfill{ outline: none; }

Am I doing something wrong?

答:
Requires this script to be added as per model-viewer official documentation </p>

```<code><script src="./_model-viewer_ Interactive Example_files/focus-visible.js.download" defer=""></script>
</code>```

Title: Model-viewer outline

Body:
<!doctype html>

    <meta charset="utf-8">

<model-viewer src="shared-assets/models/Astronaut.glb" alt="A 3D model of an astronaut" auto-rotate camera-controls></model-viewer>

When you click on model viewer the outline appears, I am unable to remove the outline from the model-viewer how would one remove it?

Edit

/**
 * This is mixin function is designed to be applied to a class that inherits
 * from HTMLElement. It makes it easy for a custom element to coordinate with
 * the :focus-visible polyfill.
 *
 * @param {Function} SuperClass The base class implementation to decorate with
 * implementation that coordinates with the :focus-visible polyfill
 */
export function FocusVisiblePolyfillMixin(SuperClass) {
  var coordinateWithPolyfill = function(instance) {
    // If there is no shadow root, there is no need to coordinate with the
    // polyfill. If we already coordinated with the polyfill, we can skip
    // subsequent invokcations:
    if (
      instance.shadowRoot == null ||
      instance.hasAttribute('data-js-focus-visible')
    ) {
      return;
    }

    // The polyfill might already be loaded. If so, we can apply it to the
    // shadow root immediately:
    if (self.applyFocusVisiblePolyfill) {
      self.applyFocusVisiblePolyfill(instance.shadowRoot);
    } else {
      // Otherwise, wait for the polyfill to be loaded lazily. It might never
      // be loaded, but if it is then we can apply it to the shadow root at
      // the appropriate time by waiting for the ready event:
      self.addEventListener(
        'focus-visible-polyfill-ready',
        function() {
          self.applyFocusVisiblePolyfill(instance.shadowRoot);
        },
        { once: true }
      );
    }
  };

  // IE11 doesn't natively support custom elements or JavaScript class syntax
  // The mixin implementation assumes that the user will take the appropriate
  // steps to support both:
  return class extends SuperClass {
    // Attempt to coordinate with the polyfill when connected to the document:
    connectedCallback() {
      super.connectedCallback && super.connectedCallback();
      coordinateWithPolyfill(this);
    }
  };
}

So I added this in file name focus-visible.js

added this to html

    <model-viewer src="shared-assets/models/Astronaut.glb" alt="A 3D model of an astronaut" auto-rotate camera-controls>
    </model-viewer>

and this in css :focus-visible polyfill{ outline: none; }

Am I doing something wrong?

Body:
Requires this script to be added as per model-viewer official documentation

<script src="./_model-viewer_ Interactive Example_files/focus-visible.js.download" defer=""></script>


问:
Running Thinking Sphinx in two applications under passenger
I have two different rails applications running thinking_shpinx, and one seems to not be using the correct index.

I tried setting the port in the sphinx.yml but it seems to not have any effect.

答:
Matthew, had you set port in sphinx.yml on a per-environment basis?

ie:

```<code>development:
  port: 3312
test:
  port: 3313
production:
  port: 3312
</code>```

OwnerDisplayName: MatthewFord

ContentLicense: CC BY-SA 2.5

Body:
Matthew, had you set port in sphinx.yml on a per-environment basis?

ie:

development:
  port: 3312
test:
  port: 3313
production:
  port: 3312

OwnerDisplayName: pat


问:
Get all posts with only the author's name
I have set a eloquent relationship between my User and Post models and in the migrations, the only thing that points to the Post author is his ID.
I'm building a VueJS Spa frontend and I was wondering how can I get all posts including but only limited to the authors ID and Name+Lastname.

I've heard of DB query builder, but I'd like to strafe away from it.

Currently, I'm grabbing everything with $posts = Post::all(); and this is the response:

```<code>    {
      "id": 3,
      "author": 1,
      "subject": "Post subject",
      "content": "The post content!!!!",
      "created_at": "2020-05-31T02:08:53.000000Z",
      "updated_at": "2020-05-31T02:08:53.000000Z"
    }
</code>```

As you can see, there is the "author" field which points to the User ID. I don't want to grab the whole user information due to security reasons and unnecessity.

Post model relation:

```<code>public function user() {
    return $this->belongsTo('App\User')->select(array('id','name'));
}
</code>```

User model relation:

```<code>public function posts() {
    return $this->hasMany('App\Post');
}
</code>```

I've also tried:
Post::with('user:id,name,lastName')->get()
but the user returns null.

答:
As @porloscerrosΨ said you should specify second argument which is foreign key and also I believe you should select author in your query too.

Your relation

public function user()
{
    return $this->belongsTo(User::class, 'author');
}
```

<p>The query  </p>

<pre class="lang-php prettyprint-override"><code>Post::with('user:id,author,name,lastName')->get()
</code>```

Body:
I have set a eloquent relationship between my User and Post models and in the migrations, the only thing that points to the Post author is his ID.
I'm building a VueJS Spa frontend and I was wondering how can I get all posts including but only limited to the authors ID and Name+Lastname.

I've heard of DB query builder, but I'd like to strafe away from it.

Currently, I'm grabbing everything with $posts = Post::all(); and this is the response:

    {
      "id": 3,
      "author": 1,
      "subject": "Post subject",
      "content": "The post content!!!!",
      "created_at": "2020-05-31T02:08:53.000000Z",
      "updated_at": "2020-05-31T02:08:53.000000Z"
    }

As you can see, there is the "author" field which points to the User ID. I don't want to grab the whole user information due to security reasons and unnecessity.

Post model relation:

public function user() {
    return $this->belongsTo('App\User')->select(array('id','name'));
}

User model relation:

public function posts() {
    return $this->hasMany('App\Post');
}

I've also tried:
Post::with('user:id,name,lastName')->get()
but the user returns null.

Body:
As @porloscerrosΨ said you should specify second argument which is foreign key and also I believe you should select author in your query too.

Your relation

public function user()
{
    return $this->belongsTo(User::class, 'author');
}

The query

Post::with('user:id,author,name,lastName')->get()


问:
JS: Touch equivalent for mouseenter
is there a touch equivalent of the mouseenter.

I would like to detect if user slide on my DIV.

I prefer a solution depending directly on the target element not on a parent element with recounting positions etc.

The site: http://dizzyn.github.io/piano-game/ - works fine with mouse (mouse down and slide; not working with touch slide)

Thank you

答:
I just wanted to say thank you to the previous poster. His suggestion worked perfectly. And I've been struggling to find a solution to this for weeks. If you're using Svelte within your pointerdown handler function I would suggest using:

const pointerDownHandler = (event) => {
    // whatever logic you need
    event.target.releasePointerCapture(event.pointerId);
}
```

He's accurate in saying this part is key. It will not work without it.

ContentLicense: CC BY-SA 3.0

Title: JS: Touch equivalent for mouseenter

Body:
I just wanted to say thank you to the previous poster. His suggestion worked perfectly. And I've been struggling to find a solution to this for weeks. If you're using Svelte within your pointerdown handler function I would suggest using:

const pointerDownHandler = (event) => {
    // whatever logic you need
    event.target.releasePointerCapture(event.pointerId);
}

He's accurate in saying this part is key. It will not work without it.


问:
How make a request in the browser to a DELETE http method in ASP.NET (.NET FRAMEWORK)
In laravel or some express.js libs add middleware to check if a field is given called _Method which will override the actual http method of the http request on arrival of the server, because the browser only supports POST and GET.

Does ASP.NET (.NET Framework) contain a build-in middleware like those I just mentioned, I couldn't find anything online.

If so, how do I use it or do you know such an atricle.

If not, how can I create such a middleware myself.

I could not create one myself, because the HttpRequest in the HttpContext is readonly and the HttpMethod in the HttpRequest is readonly aswell.

Or is the only choice to use preventDefault() and/or ajax to send (for example) a DELETE request via javascript?

答:
First of all, you need to assign [HttpDelete] attribute to your function in the controller or API. for example:

```<code>[HttpDelete]
public JsonResult MyDeleteFunction(int id)
{
    //Write your delete code here
    return Json("some responses");
}
</code>```

Then in client-side, you can use ajax to do the delete request.

```<code>$.ajax({
    url: '/ControllerName/MyDeleteFunction',
    dataType: "json",
    type: "DELETE",
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify({id: 123}),
    async: true,
    processData: false,
    cache: false,
    success: function (data) {
        alert(data);
    },
    error: function (xhr) {
        alert('error');
    }
});
</code>```

Body:
First of all, you need to assign [HttpDelete] attribute to your function in the controller or API. for example:

[HttpDelete]
public JsonResult MyDeleteFunction(int id)
{
    //Write your delete code here
    return Json("some responses");
}

Then in client-side, you can use ajax to do the delete request.

$.ajax({
    url: '/ControllerName/MyDeleteFunction',
    dataType: "json",
    type: "DELETE",
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify({id: 123}),
    async: true,
    processData: false,
    cache: false,
    success: function (data) {
        alert(data);
    },
    error: function (xhr) {
        alert('error');
    }
});


问:
Why is this code not working? (Signing into google with Selenium-Java)
I have a school project where I want to sign into Google Drive with Selenium-Java and the code to use the "Enter Email or Phone" Box always says it cannot find that element. I have tried every single method of findElement. Css-selector, ID, Linktext, Name, xPath. All of them lead to "NoSuchElementException".</p>

```<code>import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.WebDriver;
import java.util.Scanner;

public class finalProject {
    static WebDriver driver;
    static Scanner s = new Scanner(System.in);
    public static void launchBrowser() {

        // looking through my PC and running the chrome webdriver .exe file

        System.setProperty("webdriver.chrome.driver", "C:\\Users\\Lupus\\Downloads\\chromedrivernew\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.get("http://drive.google.com"); // opening google drive's site
    }
    public static void signIn() {
        driver.findElement(By.linkText("Go to Drive")).click(); // clicking the "go to drive" button

        System.out.print("Email: ");
        String email = s.nextLine();
        System.out.print("Password: ");
        String pass = s.nextLine();

        WebElement email_field = driver.findElement(By.id("identifierId"));
        email_field.sendKeys(email);
    }
    public static void main(String[] args) {
        launchBrowser();
        System.out.println("Welcome to Google Drive! First, log into your Google Account.");
        signIn();

    }
}
</code>```

答:
This solves your problem. Recommend you take a look.

The element isn't visible so due to an permanent overlay.

Replace first line in signIn() method with:

```<code>WebElement ele = driver.findElement(
//                By.xpath("//*[@id=\"start\"]/section[4]/div/div/div/a[3]")
                By.linkText("Go to Google Drive") // Both ^ works. Use one.
        );
        JavascriptExecutor executor = (JavascriptExecutor)driver;
        executor.executeScript("arguments[0].click();", ele);
</code>```

Body:
I have a school project where I want to sign into Google Drive with Selenium-Java and the code to use the "Enter Email or Phone" Box always says it cannot find that element. I have tried every single method of findElement. Css-selector, ID, Linktext, Name, xPath. All of them lead to "NoSuchElementException".

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.WebDriver;
import java.util.Scanner;

public class finalProject {
    static WebDriver driver;
    static Scanner s = new Scanner(System.in);
    public static void launchBrowser() {

        // looking through my PC and running the chrome webdriver .exe file

        System.setProperty("webdriver.chrome.driver", "C:\\Users\\Lupus\\Downloads\\chromedrivernew\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.get("http://drive.google.com"); // opening google drive's site
    }
    public static void signIn() {
        driver.findElement(By.linkText("Go to Drive")).click(); // clicking the "go to drive" button

        System.out.print("Email: ");
        String email = s.nextLine();
        System.out.print("Password: ");
        String pass = s.nextLine();

        WebElement email_field = driver.findElement(By.id("identifierId"));
        email_field.sendKeys(email);
    }
    public static void main(String[] args) {
        launchBrowser();
        System.out.println("Welcome to Google Drive! First, log into your Google Account.");
        signIn();

    }
}

Body:
This solves your problem. Recommend you take a look.

The element isn't visible so due to an permanent overlay.

Replace first line in signIn() method with:

WebElement ele = driver.findElement(
//                By.xpath("//*[@id=\"start\"]/section[4]/div/div/div/a[3]")
                By.linkText("Go to Google Drive") // Both ^ works. Use one.
        );
        JavascriptExecutor executor = (JavascriptExecutor)driver;
        executor.executeScript("arguments[0].click();", ele);