Thread: Accessing NULL in Elf

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871

    Accessing NULL in Elf

    I'm trying to retrieve the size of some callbacks because I have to manually duplicate them for the sake of passing specific lua calls relative to the glut window they were assigned. I got this far but the app segfaults at the start of the function:
    Code:
    #if __INTPTR_WIDTH__ == 32
    #define ELF_T( NAME ) Elf32_##NAME
    #elif __INTPTR_WIDTH__ == 64
    #define ELF_T( NAME ) Elf64_##NAME
    #else
    #define ELF_T( NAME ) Elf_##NAME
    #endif
    void get_cb_sizes( foo_cb_info_t *callbacks ) {
    #ifdef __ELF__
    	ELF_T(Ehdr) const *elf_header = NULL;
    	ELF_T(Phdr) const *program_headers =
    		(ELF_T(Phdr) const *)elf_header->e_phoff,
    		*program_header = NULL;
    	ELF_T(Shdr) const *section_headers =
    		(ELF_T(Shdr) const *)elf_header->e_shoff,
    		*section_header = NULL;
    	ELF_T(Sym) const *symbols = NULL, *symbol = NULL;
    	ELF_T(Half) section_index, symbol_index, symbol_count = 0;
    	foo_cb_id_t foo_cb_id;
    	if ( section_headers ) {
    		for (
    			section_index = 0;
    			section_index < elf_header->e_shnum;
    			++section_index
    		)
    		{
    			section_header = &(section_headers[section_index]);
    			if ( section_header->sh_type == SHT_SYMTAB )
    				break;
    		}
    		if ( section_index == elf_header->e_shnum ) {
    			puts("Section '.symtab' missing!");
    			exit(EXIT_FAILURE);
    		}
    		symbols = (ELF_T(Sym) const *)(section_header->sh_offset);
    		symbol_count = section_header->sh_size / sizeof(ELF_T(Sym));
    	}
    	else if ( program_headers ) {
    		program_header = &(program_headers[0]);
    		puts("Program headers not supported yet!");
    		exit(EXIT_FAILURE);
    	}
    	if ( symbols && symbol_count ) {
    		for (
    			symbol_index = 0;
    			symbol_index < symbol_count;
    			++symbol_index
    		)
    		{
    			symbol = &(symbols[symbol_index]);
    			for (
    				foo_cb_id = 0;
    				foo_cb_id < foo_cb_id_count;
    				++foo_cb_id
    			)
    			{
    				if ( symbol->st_value ==
    					(ELF_T(Off))callbacks[foo_cb_id].foo_cb ) {
    					callbacks[foo_cb_id].size = symbol->st_size;
    				}
    			}
    		}
    	}
    #else
    	puts("Must be compiled as an elf!");
    	exit(EXIT_FAILURE);
    #endif
    }
    Any help in getting this to work would be appreciated

    Edit: Forgot to copy the ELF_T define, added it in now
    Last edited by awsdert; 01-03-2020 at 05:46 AM.

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871
    I ended up doing it this way:
    Code:
    #if __INTPTR_WIDTH__ == 32
    #define ELF_T( NAME ) Elf32_##NAME
    #elif __INTPTR_WIDTH__ == 64
    #define ELF_T( NAME ) Elf64_##NAME
    #else
    #define ELF_T( NAME ) Elf_##NAME
    #endif
    void get_cb_sizes( char *name ) {
    #ifdef __ELF__
    	uchar *buff = calloc(BUFSIZ,1), *temp = NULL;
    	char *text;
    	if ( !buff ) exit(ENOMEM);
    	FILE *file = fopen(name,"r");
    	if ( !file ) {
    		free(buff);
    		exit(errno);
    	}
    	fread( buff, BUFSIZ, 1, file );
    	ELF_T(Ehdr) *elf_header = (ELF_T(Ehdr) *)buff;
    	ELF_T(Shdr) *sec_headers = NULL, *sec_header = NULL;
    	ELF_T(Sym) *syms = NULL, *sym = NULL;
    	size_t prev = BUFSIZ, need = 0, info = 0, symtabi = 0,
    		symtabs_used = 0, strtabs_used = 0, strtabs_upto = 10;
    	ELF_T(Half) sectioni, symi, sym_count = 0,
    		symtabs[10] = {0}, strtabs[10] = {0};
    	foo_cb_id_t foo_cb_id;
    	sec_headers = (ELF_T(Shdr)*)elf_header->e_shoff;
    	if ( elf_header->e_phoff > elf_header->e_shoff )
    		need = elf_header->e_phoff +
    			(elf_header->e_phnum * sizeof(ELF_T(Phdr)));
    	else
    		need = elf_header->e_shoff +
    			(elf_header->e_shnum * sizeof(ELF_T(Shdr)));
    	if ( elf_header->e_shstrndx + BUFSIZ > need )
    		need = elf_header->e_shstrndx + BUFSIZ;
    	if ( elf_header->e_entry > need )
    		need = elf_header->e_entry;
    	if ( need > prev ) {
    		temp = realloc( buff, need );
    		if ( !temp ) goto failed;
    		buff = temp;
    		fseek( file, 0, SEEK_SET );
    		fread( buff, need, 1, file );
    		prev = need;
    		elf_header = (ELF_T(Ehdr)*)buff;
    		sec_headers = (ELF_T(Shdr)*)&(buff[elf_header->e_shoff]);
    	}
    	printf("e_shoff %zu...\n", elf_header->e_shoff );
    	if ( sec_headers ) {
    		for (
    			sectioni = 0;
    			sectioni < elf_header->e_shnum;
    			++sectioni
    		)
    		{
    			sec_header = &(sec_headers[sectioni]);
    			if ( (sec_header->sh_type == SHT_STRTAB ||
    				sectioni == elf_header->e_shstrndx)
    				&& strtabs_used < strtabs_upto ) {
    				strtabs[strtabs_used++] = sectioni;
    				info = sec_header->sh_offset + sec_header->sh_size;
    				if ( info > need ) need = info;
    			}
    			if ( (sec_header->sh_type == SHT_SYMTAB
    				|| sec_header->sh_type == SHT_DYNSYM)
    				&& symtabs_used < strtabs_upto ) {
    				symtabs[symtabs_used++] = sectioni;
    				info = sec_header->sh_offset + sec_header->sh_size;
    				if ( info > need ) need = info;
    			}
    		}
    		if ( symtabs_used == 0 ) {
    			puts("Section '.symtab' missing!");
    			exit(EXIT_FAILURE);
    		}
    		if ( need > prev ) {
    			temp = realloc( buff, need );
    			if ( !temp ) goto failed;
    			buff = temp;
    			fseek( file, 0, SEEK_SET );
    			fread( buff, need, 1, file );
    			prev = need;
    			elf_header = (ELF_T(Ehdr)*)buff;
    			sec_headers = (ELF_T(Shdr)*)&(buff[elf_header->e_shoff]);
    		}
    	}
    	if ( symtabs_used ) {
    		for ( symtabi = 0; symtabi < symtabs_used; ++symtabi )
    		{
    			printf("Entering symbol list %zu...\n", symtabi );
    			sec_header = &(sec_headers[symtabs[symtabi]]);
    			syms = (ELF_T(Sym)*)&(buff[sec_header->sh_offset]);
    			sym_count = sec_header->sh_size / sizeof(ELF_T(Sym));
    			sec_header = &(sec_headers[sec_header->sh_link]);
    			text = (char*)&(buff[sec_header->sh_offset]);
    			for ( symi = 0; symi < sym_count; ++symi )
    			{
    				sym = &(syms[symi]);
    				name = &(text[sym->st_name]);
    				//printf("Checking symbol %u '%s'...\n", symi, name );
    				for (
    					foo_cb_id = 0;
    					foo_cb_id < foo_cb_id_count;
    					++foo_cb_id
    				)
    				{
    					if ( strcmp(name,foo_callbacks[foo_cb_id].name) ==0) {
    						foo_callbacks[foo_cb_id].size = sym->st_size;
    					}
    				}
    			}
    		}
    	}
    	if ( buff ) free(buff);
    	if ( file ) fclose(file);
    	return;
    	failed:
    	if ( buff ) free(buff);
    	if ( file ) fclose(file);
    	exit(errno);
    #else
    	puts("Must be compiled as an elf!");
    	exit(EXIT_FAILURE);
    #endif
    }
    
    int main( int argc, char *argv[] ) {
    	foo_cb_info_t callbacks[foo_cb_id_count] = {
    		FOO_CB_INFO(foo_cb_close),
    		FOO_CB_INFO(foo_cb_display),
    		FOO_CB_INFO(foo_cb_idle),
    		FOO_CB_INFO(foo_cb_keyboard),
    		FOO_CB_INFO(foo_cb_reshape),
    		FOO_CB_INFO(foo_cb_special),
    	};
    	g_argc = argc;
    	g_argv = argv;
    	atexit(foo_atexit);
    	memcpy( foo_callbacks, callbacks, sizeof(foo_cb_info_t) * foo_cb_id_count );
    	get_cb_sizes(argv[0]);
    ...
    Now I'm getting this issue:
    Code:
    malloc(): invalid size (unsorted)
    So I've still gotta figure out if I'm duplicating it properly but I do get as far as the call to glutCreateWindow() so no longer having issues finding the size of them

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871
    I'm gonna take a break for now, if anyone wants to help this is currently how I'm duplicating the functions and why I need to do so:
    Code:
    typedef struct foo_cb_info {
    	size_t pos;
    	size_t size;
    	char *name;
    	void *cb;
    } foo_cb_info_t;
    #define FOO_CB_INFO(NAME) {0,0,#NAME,(void*)NAME}
    typedef enum foo_cb_id {
    	foo_cb_id_close,
    	foo_cb_id_display,
    	foo_cb_id_idle,
    	foo_cb_id_keyboard,
    	foo_cb_id_reshape,
    	foo_cb_id_special,
    	foo_cb_id_count,
    } foo_cb_id_t;
    foo_cb_info_t foo_callbacks[foo_cb_id_count] = {{0}};
    typedef struct foo_window {
    	int window_id;
    	int parent_id;
    	int lua_cb[foo_cb_id_count];
    	void *foo_cb[foo_cb_id_count];
    } foo_window_t;
    int g_windows_used = 0;
    int g_windows_upto = 0;
    foo_window_t **g_windows = NULL;
    int g_current_window = 0;
    void foo_cb_close() {
    	volatile int *lua_cb = (int*)(((uintptr_t)(&lua_cb)
    		- foo_callbacks[foo_cb_id_close].pos)
    		+ (sizeof(int) * 2) + (sizeof(int) * foo_cb_id_close));
    	if ( *lua_cb == 0 ) return;
    ...
    int foo_need_window() {
    	uchar *mem;
    	size_t pos, i, need;
    	foo_cb_info_t *info;
    	foo_window_t **windows = g_windows, *window;
    	if ( g_windows_upto < 0 ) g_windows_upto = 0;
    	if ( g_windows_used >= g_windows_upto ) {
    		windows = foo_alloc( NULL, windows,
    			g_windows_upto * sizeof(foo_window_t*),
    			(g_windows_used + 100) * sizeof(foo_window_t*) );
    		if ( !windows ) return errno;
    		g_windows = windows;
    		g_windows_upto = g_windows_used + 100;
    	}
    	g_current_window = g_windows_used++;
    	pos = sizeof(foo_window_t);
    	for ( i = 0; i < foo_cb_id_count; ++i ) {
    		info = &(foo_callbacks[i]);
    		if ( !info->size ) {
    			puts("info->size was 0!");
    			exit(ERANGE);
    		}
    		info->pos = pos;
    		need = info->size + (sizeof(int) - (info->size % sizeof(int)));
    		pos += need;
    	}
    	window = g_windows[g_current_window] = calloc( pos, 1 );
    	if ( !window ) return errno;
    	mem = (uchar*)window;
    	for ( i = 0; i < foo_cb_id_count; ++i ) {
    		info = &(foo_callbacks[i]);
    		window->foo_cb[i] = &mem[pos];
    		(void)memcpy(
    			&(mem[pos]),
    			info->cb,
    			info->size );
    	}
    	return EXIT_SUCCESS;
    }

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871
    Well I came back to it and did some research, learned that I couldn't use malloc for this purpose and had to write a whole function for executable memory explicitly, somehow segfaulting after I call it though, the line where I can catch the segfault is at the bottom of the below code, the top half is the code I use before the segfault:
    Code:
    typedef struct foo_addr {
    	size_t cap;
    	uchar *foo, *mem;
    	struct foo_addr *nxt, *prv;
    } foo_addr_t;
    typedef struct foo_page {
    	size_t cap;
    	uchar *mem;
    	struct foo_addr * one;
    } foo_page_t;
    size_t pages_size = 0, pages_want = 0;
    size_t pages_used = 0, pages_upto = 0, pages_node = 0;
    foo_page_t* pages;
    int foo_size_exemem( void **dst, size_t want ) {
    	void *tmp = NULL;
    	foo_page_t *page = NULL;
    	foo_addr_t *addr = NULL, *prev;
    	size_t i = 0;
    	if ( !dst ) return EDESTADDRREQ;
    	if ( !want ) {
    		if ( *dst ) {
    			for ( i = 0; i < pages_used; ++i ) {
    				page = &(pages[i]);
    				for ( addr = page->one;
    					addr->nxt; addr = addr->nxt ) {
    					if ( addr->mem == *dst ) {
    						*dst = NULL;
    						addr->mem = NULL;
    						return EXIT_SUCCESS;
    					}
    				}
    			}
    			return EINVAL;
    		}
    		return EXIT_SUCCESS;
    	}
    	if ( *dst ) return EINVAL;
    	if ( pages_used == pages_upto ) {
    		pages_want = sizeof(foo_page_t) * (pages_used + 100);
    		tmp = realloc((void*)pages, pages_want);
    		if ( !tmp ) return ENOMEM;
    		pages = (foo_page_t*)tmp;
    		pages_upto += 100;
    		pages_size = pages_want;
    	}
    	for ( i = 0; i < pages_used; ++i ) { 
    		page = &(pages[i]);
    		if ( page->cap >= want ) {
    			for ( addr = page->one;
    				addr->nxt; addr = addr->nxt ) {
    				if ( !addr->mem && addr->cap >= want ) {
    					addr->mem = (uchar*)(addr + sizeof(foo_addr_t));
    					*dst = addr->mem;
    					return EXIT_SUCCESS;
    				}
    			}
    			addr->cap = want;
    			addr->foo = page->mem;
    			addr->mem = (uchar*)(addr + sizeof(foo_addr_t));
    			prev = addr;
    			addr = (foo_addr_t*)(addr->mem + want);
    			prev->nxt = addr;
    			page->cap -= want;
    			*dst = prev->mem;
    			return EXIT_SUCCESS;
    		}
    	}
    	page = &(pages[i]);
    	page->cap = sysconf(_SC_PAGESIZE);
    	page->mem = (uchar*)mmap( NULL, page->cap,
    		PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, 0, 0);
    	if ( !(page->mem) ) return errno;
    	++pages_used;
    	addr = page->one = (foo_addr_t*)page->mem;
    	addr->cap = want;
    	addr->foo = page->mem;
    	addr->mem = (uchar*)(addr + sizeof(foo_addr_t));
    	prev = addr;
    	addr = (foo_addr_t*)(addr->mem + want);
    	prev->nxt = addr;
    	page->cap -= want;
    	*dst = prev->mem;
    	return EXIT_SUCCESS;
    }
    void foo_free_exemem() {
    	size_t i;
    	for ( i = 0; i < pages_used; ++i )
    		munmap( pages[i].mem, sysconf(_SC_PAGESIZE) );
    	free(pages);
    	pages = NULL;
    	pages_used = pages_upto = 0;
    	pages_size = pages_want = 0;
    }
    int foo_need_window() {
    	uchar *mem;
    	size_t pos, i, need;
    	foo_cb_info_t *info;
    	foo_window_t **windows = g_windows, *window;
    	if ( g_windows_upto < 0 ) g_windows_upto = 0;
    	if ( g_windows_used >= g_windows_upto ) {
    		windows = foo_alloc( NULL, windows,
    			g_windows_upto * sizeof(foo_window_t*),
    			(g_windows_used + 100) * sizeof(foo_window_t*) );
    		if ( !windows ) return errno;
    		g_windows = windows;
    		g_windows_upto = g_windows_used + 100;
    	}
    	g_current_window = g_windows_used++;
    	pos = sizeof(foo_window_t);
    	for ( i = 0; i < foo_cb_id_count; ++i ) {
    		info = &(foo_callbacks[i]);
    		if ( !info->size ) {
    			puts("info->size was 0!");
    			exit(ERANGE);
    		}
    		info->pos = pos;
    		need = info->size + (sizeof(int) - (info->size % sizeof(int)));
    		pos += need;
    	}
    	errno = foo_size_exemem( (void**)(&window), pos );
    	if ( !window ) return errno;
    	(void)memset( window, 0, pos );
    	g_windows[g_current_window] = window;
    	mem = (uchar*)window;
    	for ( i = 0; i < foo_cb_id_count; ++i ) {
    		info = &(foo_callbacks[i]);
    		window->foo_cb[i] = &mem[info->pos];
    		(void)memcpy(
    			&(mem[info->pos]),
    			info->cb,
    			info->size );
    	}
    	return EXIT_SUCCESS;
    }
    ...
    char const* foo_getstring( lua_State *L, int pos ) {
    	if ( lua_isstring(L,pos) ) // Segfault inside this call
    		return lua_tostring(L,pos);
    	return NULL;
    }
    ...
    int foo_glutCreateWindow( lua_State *L ) {
    	int ret = foo_need_window();
    	char const *title = foo_getstring( L, -1 );
    ...

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871
    Well now I know for sure there's some problem with my allocation method, I tried modifying my code to support realloc like behaviour and then modified my foo_alloc() function (which lua relies on) to use that instead, this is the code with an added comment at where it segfaults:
    Code:
    typedef struct foo_addr {
    	size_t size;
    	void *page, *data;
    	struct foo_addr *next, *prev;
    } foo_addr_t;
    typedef struct foo_page {
    	size_t cap;
    	uchar *mem;
    	struct foo_addr * one;
    } foo_page_t;
    size_t pages_size = 0, pages_want = 0;
    size_t pages_used = 0, pages_upto = 0, pages_node = 0;
    foo_page_t* pages;
    int foo_find_addr_in_pages( void *ptr, foo_addr_t **dst ) {
    	size_t i = 0;
    	foo_page_t *page;
    	foo_addr_t *addr;
    	if ( !dst ) return EDESTADDRREQ;
    	if ( ptr ) {
    		for ( i = 0; i < pages_used; ++i ) {
    			page = &(pages[i]);
    			for ( addr = page->one;
    				addr->next; addr = addr->next ) {
    				if ( addr->data == ptr ) {
    					*dst = addr;
    					return EXIT_SUCCESS;
    				}
    			}
    		}
    		return EINVAL;
    	}
    	return EXIT_FAILURE;
    }
    void foo_new_page_addr(
    	foo_page_t *page, foo_addr_t *addr, foo_addr_t *next, size_t want ) {
    	addr->size = want;
    	addr->page = page->mem;
    	addr->data = (addr + sizeof(foo_addr_t));
    	if ( next ) addr->next = next;
    	next = (foo_addr_t*)((uintptr_t)(addr->data) + want);
    	if ( addr->next ) next->next = addr->next;
    	addr->next = next;
    	next->prev = addr;
    	next->size = sysconf(_SC_PAGESIZE) -
    		(uintptr_t)(next + sizeof(foo_addr_t));
    }
    int foo_find_memory( foo_page_t **base,
    	foo_addr_t **dst, foo_addr_t **nxt, size_t want ) {
    	foo_page_t *page = NULL;
    	foo_addr_t *next = NULL, *addr = NULL;
    	size_t p, size = 0;
    	for ( p = 0; p < pages_used; ++p ) {
    		page = &(pages[p]);
    		addr = page->one;
    		while ( addr ) {
    			if ( addr->data ) continue;
    			next = addr;
    			size = 0;
    			while ( size < want ) {
    				if ( next->data ) break;
    				size += next->size;
    				next = next->next;
    				if ( !next ) break;
    			}
    			if ( size >= want ) {
    				*base = page;
    				*dst = addr;
    				*nxt = next;
    				return EXIT_SUCCESS;
    			}
    			if ( !next ) break;
    			addr = next->next;
    		}
    	}
    	if ( pages_used == pages_upto ) {
    		pages_want = sizeof(foo_page_t) * (pages_used + 100);
    		page = (foo_page_t*)realloc((void*)pages, pages_want);
    		if ( !page ) return ENOMEM;
    		pages = page;
    		pages_upto += 100;
    		pages_size = pages_want;
    	}
    	page = &(pages[p]);
    	page->cap = sysconf(_SC_PAGESIZE);
    	page->mem = (uchar*)mmap( NULL, page->cap,
    		PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, -1, -1);
    	if ( !(page->mem) ) return errno;
    	++pages_used;
    	addr = page->one = (foo_addr_t*)page->mem;
    	addr->size = sysconf(_SC_PAGESIZE) - sizeof(foo_addr_t); // here is where it segfaults
    	*base = page;
    	*dst = addr;
    	*nxt = NULL;
    	return EXIT_FAILURE;
    }
    int foo_size_exemem( void **dst, size_t want ) {
    	foo_page_t *page = NULL;
    	foo_addr_t *addr = NULL, *next, *current;
    	size_t i = 0;
    	if ( !dst ) return EDESTADDRREQ;
    	if ( !want ) {
    		if ((errno = foo_find_addr_in_pages( *dst, &addr ))
    			!= EXIT_SUCCESS)
    			return errno;
    		*dst = NULL;
    		addr->data = NULL;
    		return EXIT_SUCCESS;
    	}
    	if ( *dst ) {
    		if ((errno = foo_find_addr_in_pages(*dst,&current))
    			!= EXIT_SUCCESS )
    			return errno;
    		if ( want < current->size ) {
    			foo_new_page_addr( page, current, NULL, want );
    			return EXIT_SUCCESS;
    		}
    		if ( want == current->size ) return EXIT_SUCCESS;
    		i = 0;
    		addr = current;
    		while ( i < want ) {
    			if ( !addr || addr->data ) break;
    			i += addr->size;
    			addr = addr->next;
    			if ( !addr ) break;
    		}
    		if ( i >= want ) {
    			foo_new_page_addr( page, current, addr, want );
    			return EXIT_SUCCESS;
    		}
    		if ( (errno = foo_find_memory( &page, &addr, &next, want ))
    			!= EXIT_SUCCESS )
    			return errno;
    		foo_new_page_addr( page, addr, next, want );
    		memcpy( current->data, addr->data, current->size );
    		*dst = addr->data;
    		current->data = NULL;
    		return EXIT_SUCCESS;
    	}
    	if ( (errno = foo_find_memory( &page, &addr, &next, want ))
    		!= EXIT_SUCCESS )
    		return errno;
    	foo_new_page_addr( page, addr, next, want );
    	*dst = addr->data;
    	return EXIT_SUCCESS;
    }
    void foo_free_exemem() {
    	size_t i;
    	for ( i = 0; i < pages_used; ++i )
    		munmap( pages[i].mem, sysconf(_SC_PAGESIZE) );
    	free(pages);
    	pages = NULL;
    	pages_used = pages_upto = 0;
    	pages_size = pages_want = 0;
    }
    void *foo_alloc( void *ud, void *ptr, size_t size, size_t want ) {
    	uchar *tmp = NULL;
    	(void)ud;
    	errno = EXIT_SUCCESS;
    	if ( want == size ) return ptr;
    	if ( !want ) {
    		if ( ptr ) foo_size_exemem( &ptr, 0 );
    		return NULL;
    	}
    	tmp = ptr;
    	if ( (errno = foo_size_exemem( (void**)(&tmp), want ))
    		!= EXIT_SUCCESS )
    		goto nomem;
    	if ( !ptr ) memset( tmp, 0, want );
    	if ( size < want ) memset( &tmp[size], 0, want - size );
    	return tmp;
    	nomem:
    	if ( errno == EXIT_SUCCESS ) errno = ENOMEM;
    	return NULL;
    }

  6. #6
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    871
    Found the main issue, was return EXIT_FAILURE instead of EXIT_SUCCESS after retrieving the page, now I got an infinite loop somewhere so time for more debugging

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Null
    By RyanC in forum C Programming
    Replies: 11
    Last Post: 01-10-2016, 11:55 AM
  2. assign null value to a struct and check if it is null
    By ymc1g11 in forum C Programming
    Replies: 10
    Last Post: 11-01-2012, 03:58 PM
  3. Replies: 9
    Last Post: 10-20-2007, 01:05 AM
  4. Replies: 3
    Last Post: 12-23-2006, 06:57 PM
  5. accept(ListenSocket, NULL, NULL); cause program to hang?
    By draggy in forum Networking/Device Communication
    Replies: 11
    Last Post: 06-16-2006, 03:40 PM

Tags for this Thread