json-c: segmentation fault when in json_tokener_parse - json-c

I am using json-c to parse json files in my project. I tried creating json_tokener_parse but this has resulted in seg-fault. could any please check and tell me the reason for segfault.
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h> // O_RDONLY
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<json-c/json.h>
int main() {
int oflag = O_RDONLY;
const char *path = "file.json";
const int fd = open(path, oflag);
// use stat to find the file size
struct stat stat;
int ret = fstat(fd, &stat);
int mflags = MAP_SHARED; // information about handling the mapped data
int mprot = PROT_READ|PROT_WRITE; // access permissions to the data being mapped
size_t size = stat.st_size;
void *addr = mmap(NULL, size, mprot, mflags, fd, 0);
const char *file = (char *)addr;
json_object * jobj = json_tokener_parse(addr);
//json_parse(jobj);
}

json_tokener_parse() takes a null-terminated string. A text file is not null-terminated. You'll have to use json_tokener_parse_ex() and specify the length.

Related

Wide-character string converted from multibyte string using MultiByteToWideChar print and write to file error

I can print the wide-character string correctly, writing to text file is also OK, using the following code:
const wchar_t wcs[] = L"Hello大家好";
_setmode(_fileno(stdout), _O_WTEXT);
wprintf(L"%ls", wcs);
FILE *pf;
const wchar_t _FileName[] = L"wcs.txt";
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", wcs);
fflush(pf);
fclose(pf);
But I need to convert the multibyte string to wide-character string, using MultiByteToWideChar, and than print or write to text file, error occurred, the result displayed or the text file is all messy code. My code is below.
const char cs[] = "Hello大家好";
wchar_t lpWideCharStr[64];
MultiByteToWideChar(CP_ACP, 0, cs, 0, lpWideCharStr, 64);
wprintf(L"%ls", lpWideCharStr);
FILE *pf;
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", lpWideCharStr);
fflush(pf);
fclose(pf);
Can anybody help? Thanks in advance.
This works for me.
#include <Windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
bool ConvertToWideFromUTF8orACP(char* strData, wchar_t* w_strData, int w_strDataLen)
{
int nSize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, strData, -1, w_strData, w_strDataLen);
if (nSize == 0)
{
nSize = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, strData, -1, w_strData, w_strDataLen);
}
return nSize - 1;
}
int main()
{
char cs[] = "Hello大家好";
printf("%s\n", cs);
wchar_t* lpWideCharStr = new wchar_t[sizeof(cs)];
memset(lpWideCharStr, 0, sizeof(cs));
int nSize = ConvertToWideFromUTF8orACP(cs, lpWideCharStr,sizeof(cs));
_setmode(_fileno(stdout), _O_U16TEXT);
if (nSize > 0)
{
wprintf(L"%s", lpWideCharStr);
}
FILE* pf;
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", lpWideCharStr);
delete[] lpWideCharStr;
fflush(pf);
fclose(pf);
}
Thanks #Remy Lebeau for help:)

Writing a custom nss hosts module

I'm seeking to implement a custom nss module for the getent hosts lookup. Based on glibc's resolv/nss-dns/dns-host.c and gnunet's src/gns/nss/nss_gns.c I wrote the following minimal implementation that I hoped at least should write something to syslog - which it sadly doesn't.
#include <netdb.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#define _nss_lash_gethostbyname2_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname3_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname4_r _nss_lash_gethostbyname_r
#define _nss_lash_getcanonname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_gethostbyaddr2_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyaddr_r _nss_lash_gethostbyaddr_r
typedef char addr[1];
const addr default_addrs[2] = {0x01, 0x00};
enum nss_status
_nss_lash_gethostbyname_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_WARNING, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
enum nss_status
_nss_lash_gethostbyaddr_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
syslog(LOG_ERR, name);
if (!strcmp(name, "lash")) {
return NSS_STATUS_UNAVAIL;
}
*(result->h_aliases) = 0x0;
result->h_addrtype = AF_INET;
result->h_length = 1;
*(result->h_addr_list) = (char *)default_addrs;
*errnop = 0;
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
I've added lash to /etc/nsswitch.conf. strace shows that the /lib/libnss_lash.so.2 file is being successfully opened. However the return value from the nss lookup is NSS_UNAVAIL / ENOENT. If I add [unavail=return] to /etc/nsswitch.conf after the lash entry, I get the same result.
Anyone have any clues to what I'm missing?
(the #define lines attempt to catch all symbols found in objdump -T /lib/libnss_dns.so, which seems to be the simpler implementation)
Using:
glibc 2.30
gnunet 0.11.6-ish
nss 3.49.2

char * variable declaration

I just want to verify I got this right.
The copy from sr to ds2 gives an error. Is this because ds2 is considered "const"??
Thanks and hope this isn't a bore.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main(void)
{
char *sr = "Hello World";
char *ds1 = (char*)malloc(100 * sizeof(char));
char *ds2 = "12345678901234567890";
// This statement works just fine
printf("%s\n", strcpy(ds1, sr));
// This gives error
strcpy(ds2, sr);
printf("%s\n", ds2);
return 0;
}
Here is a similar post
difference between char* and char[] with strcpy()
When you do this
char *ds2 = "12345678901234567890";
the compiler leaves the pointer pointing to a non-writable memory region.
With this line
// This gives error
strcpy(ds2, sr);
You are trying to do an strcpy into the non-writable memory.
You should also have a free for each malloc as you are allocating memory but not de-allocating it.

Building simply download menager with libcurl on Ubuntu, in C

I'm having some problems with my code. I get segmentation code error after compiling my program. I want to build simply download tool so i'm using the simplest ideas for it.(User enters the url and program download file into users desktop). Could you give me some tips how to make this program work or how to convert it to better one (more demanding code with better results).
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
int x;
char y[200];
char page;
char outfilename[FILENAME_MAX];
char path_pdf = "/home/user_name/Desktop/document.pdf";
char path_jpg = "/home/user_name/Desktop/picture.jpg";
char path_txt = "/home/user_name/Desktop/document.txt";
char FILEPATH[2] = {path_pdf, path_jpg, path_txt};
printf("Enter file url \n"); // for example http://oi58.tinypic.com/15nk3de.jpg
scanf ("%s",y);
char *url = "y";
printf("Choose type of file:\n [0] - pdf\n [1] - jpg\n [2] - txt\n "); //choose 1
scanf("%d",x);
outfilename[FILENAME_MAX] = FILEPATH[x];
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
There are several reasons that your code isn't working:
path_pdf, path_jpg, and path_txt should be type char*
FILEPATH should be declared as char FILEPATH[3] = {path_pdf, path_jpg, path_txt}; as RaptorDotCpp pointed out.
Your second scanf call should be scanf("%d", &x); since scanf requires the arguments after the format to be pointers. This is where your code segfaulted when I tested it.
url should be initialized as char *url = y;. This sets url to the value the user entered instead of only the letter "y".
outfilename[FILENAME_MAX] = FILEPATH[x]; writes past the end of outfilename. Use outfilename = FILEPATH[x]; instead, which won't cause a buffer overflow.

Getting process base address in Mac OSX

I'm trying to read the memory of a process using task_for_pid / vm_read.
uint32_t sz;
pointer_t buf;
task_t task;
pid_t pid = 9484;
kern_return_t error = task_for_pid(current_task(), pid, &task);
vm_read(task, 0x10e448000, 2048, &buf, &sz);
In this case I read the first 2048 bytes.
This works when I know the base address of the process (which I can find out using gdb "info shared" - in this case 0x10e448000), but how do I find out the base address at runtime (without looking at it with gdb)?
Answering my own question. I was able to get the base address using mach_vm_region_recurse like below. The offset lands in vmoffset. If there is another way that is more "right" - don't hesitate to comment!
#include <stdio.h>
#include <mach/mach_init.h>
#include <sys/sysctl.h>
#include <mach/mach_vm.h>
...
mach_port_name_t task;
vm_map_offset_t vmoffset;
vm_map_size_t vmsize;
uint32_t nesting_depth = 0;
struct vm_region_submap_info_64 vbr;
mach_msg_type_number_t vbrcount = 16;
kern_return_t kr;
if ((kr = mach_vm_region_recurse(task, &vmoffset, &vmsize,
&nesting_depth,
(vm_region_recurse_info_t)&vbr,
&vbrcount)) != KERN_SUCCESS)
{
printf("FAIL");
}
Since you're calling current_task(), I assume you're aiming at your own process at runtime. So the base address you mentioned should be the dynamic base address, i.e. static base address + image slide caused by ASLR, right? Based on this assumption, you can use "Section and Segment Accessors" to get the static base address of your process, and then use the dyld functions to get the image slide. Here's a snippet:
#import <Foundation/Foundation.h>
#include </usr/include/mach-o/getsect.h>
#include <stdio.h>
#include </usr/include/mach-o/dyld.h>
#include <string.h>
uint64_t StaticBaseAddress(void)
{
const struct segment_command_64* command = getsegbyname("__TEXT");
uint64_t addr = command->vmaddr;
return addr;
}
intptr_t ImageSlide(void)
{
char path[1024];
uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) != 0) return -1;
for (uint32_t i = 0; i < _dyld_image_count(); i++)
{
if (strcmp(_dyld_get_image_name(i), path) == 0)
return _dyld_get_image_vmaddr_slide(i);
}
return 0;
}
uint64_t DynamicBaseAddress(void)
{
return StaticBaseAddress() + ImageSlide();
}
int main (int argc, const char *argv[])
{
printf("dynamic base address (%0llx) = static base address (%0llx) + image slide (%0lx)\n", DynamicBaseAddress(), StaticBaseAddress(), ImageSlide());
while (1) {}; // you can attach to this process via gdb/lldb to view the base address now :)
return 0;
}
Hope it helps!

Resources