malloc error when reading file in iOS - objective-c

i have this function that reads a line from a file character by character and inserts it into a NSString.
RANDOMNLY the system crashes with this error:
malloc: *** error for object 0x1e1f6a00: incorrect checksum for freed
object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
function:
NSDictionary *readLineAsNSString(FILE *f,int pospass,
BOOL testata, int dimensioneriga)
{
char *strRet = (char *)malloc(BUFSIZ);
int size = BUFSIZ;
BOOL finito=NO;
int pos = 0;
int c;
fseek(f,pospass,SEEK_SET);
do{ // read one line
c = fgetc(f);
//Array expansion
if (pos >= size-1) {
size=size+BUFSIZ;
strRet = (char *)realloc(strRet, size);
}
if(c != EOF) {
strRet[pos] = c;
pos=pos+1;
}
if(c == EOF) {
finito=YES;
}
} while(c != EOF && c != '\n');
if (pos!=0) {
for (int i = pos; i<=strlen(strRet)-1; i++) //size al posto di pos
{
strRet[i] = ' ';
}
}
NSString *stringa;
if (pos!=0) {
stringa=[NSString stringWithCString:strRet encoding:NSASCIIStringEncoding];
} else {
stringa=#"";
}
long long sizerecord;
if (pos!=0) {
sizerecord= (long long) [[NSString stringWithFormat:#"%ld",sizeof(char)*(pos)] longLongValue];
} else {
sizerecord=0;
}
pos = pospass + pos;
NSDictionary *risultatoc = #{st_risultatofunzione: stringa,
st_criterio: [NSString stringWithFormat:#"%d",pos],
st_finito: [NSNumber numberWithBool:finito],
st_size: [NSNumber numberWithLongLong: sizerecord]
};
//free
free(strRet);
return risultatoc;
}
where "finito" is a flag, "pos" is the position in the file line,"pospass" is the position in the entire file, "c" is the character, "strRet" is the line and BUFSIZ is 1024.
Each file has n line with the same lenght (for file).
Thanks!!!

This part:
if (pos!=0) {
for (int i = pos; i<=strlen(strRet)-1; i++) //size al posto di pos
{
strRet[i] = ' ';
}
}
is broken. strlen just reads until it finds a \0 ... since you didn't put one in, it can just keep reading off the end of your buffer.
You already have size, so just use that, or better still just terminate strRet instead of right-filling with spaces:
strRet[pos] = '\0';

Related

Quirk disappearing white space string

I run into this funny situation. I create a string containing only white space. Spaces and newlines. No matter if I create it randomly or using a loop inside a loop (lots of spaces followed by a newline). When I log the string it does not show up? Even the newline in
NSLog(#"String\n%#",s);
disappears. If I add anything that is not whitespace to s then it shows up.
Here is the code to reproduce it.
#import <Foundation/Foundation.h>
NSString * func ( BOOL f )
{
// Create a string containing only white space
NSMutableString * s = NSMutableString.string;
BOOL rand = NO;
if ( rand )
{
for ( int i = 0; i < 500; i ++ )
{
if ( arc4random_uniform(100) > 90 )
{
[s appendString:#"\n"];
}
else
{
[s appendString:#" "];
}
}
}
else
{
for ( int i = 0; i < 10; i ++ )
{
for ( int j = 0; j < 100; j ++ )
{
[s appendString:#" "];
}
[s appendString:#"\n"];
}
}
if ( f )
{
[s appendString:#"?\n"];
}
return s;
}
int main(int argc, const char * argv[]) {
#autoreleasepool
{
// insert code here...
NSLog(#"Hello, World!");
NSLog(#"The string is\n%#",func(NO));
NSLog(#"Where is it?");
// Now add something real
NSLog(#"The string is\n%#",func(YES));
NSLog(#"Oh there it is?");
}
return 0;
}
Note in main the first time func is called with BOOL NO as argument, the function just creates a bunch of whitespace. So I'd expect to see it in the log. However, the log shows nothing! Not even the newline!
Then I call the function again. This time it generates the same thing but postfixes it with a question mark and suddenly the string appears. Where did the whitespace go? Is there some funny optimisation going on? Looks like a bug.
Here is the output for reference.
2021-01-23 21:28:43.990972+0200 WhiteSpaceString[33439:733772] Hello, World!
2021-01-23 21:28:43.991845+0200 WhiteSpaceString[33439:733772] The string is
2021-01-23 21:28:43.991943+0200 WhiteSpaceString[33439:733772] Where is it?
2021-01-23 21:28:43.992171+0200 WhiteSpaceString[33439:733772] The string is
?
2021-01-23 21:28:43.997993+0200 WhiteSpaceString[33439:733772] Oh there it is?
Program ended with exit code: 0
Initially I thought maybe the function is to blame, as it returns a string but internally uses a mutable string. But even if the code is put inside main e.g.
NSMutableString * t = NSMutableString.string;
for ( int i = 0; i < 10; i ++ )
{
for ( int j = 0; j < 100; j ++ )
{
[t appendString:#" "];
}
[t appendString:#"\n"];
}
NSLog(#"The string is\n%#",t);
it still does not show the string.

unable to detect application running with another user (via switch user)

Use case: I login as "user1" and launch Safari, then I click "user1" on top-right corner and switch user to "user2".
Now, I am trying to detect whether Safari is running for "user1" but I am unable to do so with standard calls. I am using OS X 10.8 Mountain Lion for both development and running my code.
I have used the following but in vain:
[[NSWorkspace sharedWorkspace] runningApplications] - Safari not there in the list
GetNextProcess() - Safari does not come up
GetProcessForPID() - I get an error "no such process"
But when I do a ps -aef | grep Safari from the terminal, I can see Safari. (This is not only the case with Safari but other applications as well.)
Can someone please help. Thank you very much.
You can use sysctl or ps command to get a list of all BSD processes.Have a look at Technical Q&A QA1123
#include <sys/sysctl.h>
#include <pwd.h>
typedef struct kinfo_proc kinfo_proc;
static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
int err;
kinfo_proc * result;
bool done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;
// assert( procList != NULL);
// assert(*procList == NULL);
// assert(procCount != NULL);
*procCount = 0;
// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we're done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.
result = NULL;
done = false;
do {
assert(result == NULL);
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0) {
result = malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
if (err == 0) {
done = true;
} else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
if (err == 0) {
*procCount = length / sizeof(kinfo_proc);
}
assert( (err == 0) == (*procList != NULL) );
return err;
}
+ (NSArray*)getBSDProcessList
{
kinfo_proc *mylist =NULL;
size_t mycount = 0;
GetBSDProcessList(&mylist, &mycount);
NSMutableArray *processes = [NSMutableArray arrayWithCapacity:(int)mycount];
for (int i = 0; i < mycount; i++) {
struct kinfo_proc *currentProcess = &mylist[i];
struct passwd *user = getpwuid(currentProcess->kp_eproc.e_ucred.cr_uid);
NSMutableDictionary *entry = [NSMutableDictionary dictionaryWithCapacity:4];
NSNumber *processID = [NSNumber numberWithInt:currentProcess->kp_proc.p_pid];
NSString *processName = [NSString stringWithFormat: #"%s",currentProcess->kp_proc.p_comm];
if (processID)[entry setObject:processID forKey:#"processID"];
if (processName)[entry setObject:processName forKey:#"processName"];
if (user){
NSNumber *userID = [NSNumber numberWithUnsignedInt:currentProcess->kp_eproc.e_ucred.cr_uid];
NSString *userName = [NSString stringWithFormat: #"%s",user->pw_name];
if (userID)[entry setObject:userID forKey:#"userID"];
if (userName)[entry setObject:userName forKey:#"userName"];
}
[processes addObject:[NSDictionary dictionaryWithDictionary:entry]];
}
free(mylist);
return [NSArray arrayWithArray:processes];
}

Objective-C: DNS TXT Record

I've been searching for a while without any success, how am I supposed to get a DNS TXT record for a domain in Objective-C?
My goal is to get the same output as: dig -t txt google.com +short
PS: No NSTask/pipping please! (I'm currently doing that but it's bad). The code can be written in C, I'll just write a wrapper later. I don't care about AppStore rules.
Thank you!
Use DNSServiceQueryRecord in dns_sd.h:
#import <dns_sd.h>
// ...
DNSServiceRef serviceRef;
DNSServiceQueryRecord(&serviceRef, 0, 0, "hmspl.de", kDNSServiceType_TXT,
kDNSServiceClass_IN, queryCallback, NULL);
DNSServiceProcessResult(serviceRef);
DNSServiceRefDeallocate(serviceRef);
// ...
static void queryCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype,
uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) {
if (errorCode == kDNSServiceErr_NoError && rdlen > 1) {
NSMutableData *txtData = [NSMutableData dataWithCapacity:rdlen];
for (uint16_t i = 1; i < rdlen; i += 256) {
[txtData appendBytes:rdata + i length:MIN(rdlen - i, 255)];
}
NSString *theTXT = [[NSString alloc] initWithBytes:txtData.bytes length:txtData.length encoding:NSASCIIStringEncoding];
NSLog(#"%#", theTXT);
}
}
See https://developer.apple.com/library/mac/#documentation/Networking/Reference/DNSServiceDiscovery_CRef/Reference/reference.html#//apple_ref/doc/c_ref/DNSServiceQueryRecord
can use like this code remove \x02 \x03, I removed \0x12 \0x17
use $man ascii check
char result[256]={0};
dn_expand(rdata, rdata + rdlen, rdata, result, 256);
NSMutableData *txtData = [NSMutableData dataWithCapacity:rdlen];
char *p=(char*)rdata;
for (uint16_t i = 0; i < rdlen; i++) {
DLog(#"%c\n",*p);
if (*p > 0x20) {
[txtData appendBytes:p length:1];
}
p++;
}

Converting NSString to array of chars inside For Loop

I'm trying to use an existing piece of code in an iOS project to alphabetize a list of words in an array (for instance, to make tomato into amoott, or stack into ackst). The code seems to work if I run it on its own, but I'm trying to integrate it into my existing app.
Each word I want it to alphabetize is stored as an NSString inside an array. The issue seems to be that the code takes the word as an array of chars, and I can't get my NSStrings into that format.
If I use string = [currentWord UTFString], I get an error of Array type char[128] is not assignable, and if I try to create the char array inside the loop (const char *string = [curentWord UTF8String]) I get warnings relating to Initializing char with type const char discards qualifiers. Not quite sure how I can get around it – any tips? The method is below, I'll take care of storing the alphabetized versions later.
- (void) alphabetizeWord {
char string[128], temp;
int n, i, j;
for (NSString* currentWord in wordsList) {
n = [currentWord length];
for (i = 0; i < n-1; i++) {
for (j = i+1; j < n; j++) {
if (string[i] > string[j]) {
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
NSLog(#"The word %# in alphabetical order is %s", currentWord, string);
}
}
This should work :
- (void)alphabetizeWord {
char str[128];
for (NSString *currentWord in wordList)
{
int wordLength = [currentWord length];
for (int i = 0; i < wordLength; i++)
{
str[i] = [currentWord characterAtIndex:i];
}
// Adding the termination char
str[wordLength] = 0;
// Add your word
}
}
EDIT : Sorry, didn't fully understand at first. Gonna check this out.

LLVM GCC 4.2 EXC_BAD_ACCESS

Below code runs just fine on GCC 4.2 but fails with EXC_BAD_ACCESS in LLVM GCC 4.2
- (double_t)readDouble {
double_t *dt = (double_t *)(buffer+offset);
double_t ret = *dt; // Program received signal: EXC_BAD_ACCESS
offset += 8;
return ret;
}
That's how I allocate
int dataLength = [data length];
buffer = malloc(dataLength + 1);
buffer[dataLength] = 0; // null terminate to log
[data getBytes:(void *)buffer length:[data length]];
//NSLog(#"%s", buffer);
Offset and buffer is like
#interface PRDataSet : NSObject {
NSMutableArray *tables;
NSMutableDictionary *tablesByName;
NSMutableDictionary *tablesById;
#private
NSURLConnection *conn;
int offset;
char *buffer;
}
Yes offset is within range.
I do not free the buffer before I use it.
Any ideas?
This could be an aligment problem. The ARM processors (and many other processors) have restrictions regarding the data alignment, e.g. they can only read and write floating-point numbers from addresses that are a multiple of 4 or 8.
From the way the buffer is allocated in your code, it might not be allocated properly, or your double_t data elements aren't aligned within the buffer.
In order to avoid the problem, you should try to first copy the data into an aligned buffer and read it from there.
LLVM just doesn't read float directly.
Here's the solution:
- (uint32_t)readUInt32 {
uint32_t ret = *(uint32_t *)(buffer+offset);
offset += 4;
return ret;
}
- (uint16_t)readUInt16 {
uint16_t ret = *(uint16_t *)(buffer+offset);
offset += 2;
return ret;
}
- (uint64_t)readUInt64 {
uint64_t ret = *(uint64_t *)(buffer+offset);
offset += 8;
return ret;
}
- (float_t)readSingle {
uint32_t t = [self readUInt32];
float_t ret = *((float_t *)(&t));
return ret;
}
- (double_t)readDouble {
uint64_t t = [self readUInt64];
double_t ret = *((double_t *)(&t));
return ret;
}