Bladeren bron

Fix bad access bugs (hopefully)

In some callbacks, NSData objects to be passed to IRCClientSession's
event handlers would be nil (if e.g. a user parted a channel without
giving a reason). Those object references would then be sent messages.
This is bad. Instead, an NSData object is always allocated now, even
for blank reasons/messages/notices/etc. This object simply contains a
single null byte (i.e. it holds an empty, null-terminated C string).
master
achmizs 10 jaren geleden
bovenliggende
commit
899a91d410
2 gewijzigde bestanden met toevoegingen van 117 en 31 verwijderingen
  1. 15
    0
      IRCClient/IRCClientSession.h
  2. 102
    31
      IRCClient/IRCClientSession.m

+ 15
- 0
IRCClient/IRCClientSession.h Bestand weergeven

#pragma mark - Class methods #pragma mark - Class methods
/***************************/ /***************************/


/** Returns a dictionary of IRC numeric codes.
The dictionary contains entries for all known IRC numeric codes (as keys).
(The list is taken from https://www.alien.net.au/irc/irc2numerics.html .)
The value for each key is an NSArray with the known numeric reply names for
which the numeric code is used.
Note that there is no gaurantee whatsoever that any given numeric reply
name will, in fact, describe the contents of the message; most IRC numeric
messages have implementation-specific uses. See the various RFCs, and other
info sources, for details.
*/
+(NSDictionary *)IRCNumericCodes;

/** Set the nickname, username, and realname for the session. /** Set the nickname, username, and realname for the session.
Returns 1 if successfully set, 0 otherwise. Returns 1 if successfully set, 0 otherwise.

+ 102
- 31
IRCClient/IRCClientSession.m Bestand weergeven



#pragma mark - IRCClientSession private category declaration #pragma mark - IRCClientSession private category declaration


static NSDictionary* ircNumericCodeList;

@interface IRCClientSession() @interface IRCClientSession()
{ {
irc_callbacks_t _callbacks; irc_callbacks_t _callbacks;


@property (readwrite) NSMutableDictionary *channels; @property (readwrite) NSMutableDictionary *channels;


+(void)loadNumericCodes;

@end @end


#pragma mark - IRCClientSession class implementation #pragma mark - IRCClientSession class implementation
irc_destroy_session(_irc_session); irc_destroy_session(_irc_session);
} }


+(NSDictionary *)IRCNumericCodes
{
if(ircNumericCodeList == nil)
{
[IRCClientSession loadNumericCodes];
}
return ircNumericCodeList;
}

+(void)loadNumericCodes
{
NSString* numericCodeListPath = [[NSBundle mainBundle] pathForResource:@"IRC_Numerics" ofType:@"plist"];
ircNumericCodeList = [NSDictionary dictionaryWithContentsOfFile:numericCodeListPath];
if(ircNumericCodeList)
{
NSLog(@"IRC numeric codes list loaded successfully.\n");
}
else
{
NSLog(@"Could not load IRC numeric codes list!\n");
}
}

- (int)connect; - (int)connect;
{ {
return irc_connect(_irc_session, _server.UTF8String, (unsigned short) _port, (_password.length > 0 ? _password.SA_terminatedCString : NULL), _nickname.UTF8String, _username.UTF8String, _realname.UTF8String); return irc_connect(_irc_session, _server.UTF8String, (unsigned short) _port, (_password.length > 0 ? _password.SA_terminatedCString : NULL), _nickname.UTF8String, _username.UTF8String, _realname.UTF8String);
[_delegate privateMessageReceived:messageString fromUser:nick]; [_delegate privateMessageReceived:messageString fromUser:nick];
} }


- (void)noticeSent:(NSData *)notice toChannel:(NSData *)channelName byUser:(NSString *)nick
- (void)privateNoticeReceived:(NSData *)notice fromUser:(NSString *)nick
{ {
IRCClientChannel *channel = _channels[channelName];
NSString* noticeString = [NSString stringWithCString:notice.SA_terminatedCString encoding:_encoding];
[channel noticeSent:notice byUser:nick];
[_delegate privateNoticeReceived:noticeString fromUser:nick];
} }


- (void)privateNoticeReceived:(NSData *)notice fromUser:(NSString *)nick
- (void)noticeSent:(NSData *)notice toChannel:(NSData *)channelName byUser:(NSString *)nick
{ {
NSString* noticeString = [NSString stringWithCString:notice.SA_terminatedCString encoding:_encoding];
IRCClientChannel *channel = _channels[channelName];
[_delegate privateNoticeReceived:noticeString fromUser:nick];
[channel noticeSent:notice byUser:nick];
} }


- (void)invitedToChannel:(NSData *)channelName by:(NSString *)nick - (void)invitedToChannel:(NSData *)channelName by:(NSString *)nick
{ {
[_delegate invitedToChannel:channelName by:nick];
[_delegate invitedToChannel:channelName.SA_dataWithTerminatedCString by:nick];
} }


- (void)CTCPRequestReceived:(NSData *)request fromUser:(NSString *)nick - (void)CTCPRequestReceived:(NSData *)request fromUser:(NSString *)nick
} }
else if (!strcmp (the_request, "VERSION")) else if (!strcmp (the_request, "VERSION"))
{ {
irc_cmd_ctcp_reply (_irc_session, the_nick, [NSString stringWithFormat:@"VERSION %@", _version].UTF8String);
irc_cmd_ctcp_reply (_irc_session, the_nick, [[NSString stringWithFormat:@"VERSION %@", _version] cStringUsingEncoding:_encoding]);
} }
else if (!strcmp (the_request, "FINGER")) else if (!strcmp (the_request, "FINGER"))
{ {
irc_cmd_ctcp_reply (_irc_session, the_nick, [NSString stringWithFormat:@"FINGER %@ (%@) Idle 0 seconds", _username, _realname].UTF8String);
irc_cmd_ctcp_reply (_irc_session, the_nick, [[NSString stringWithFormat:@"FINGER %@ (%@) Idle 0 seconds", _username, _realname] cStringUsingEncoding:_encoding]);
} }
else if (!strcmp (the_request, "TIME")) else if (!strcmp (the_request, "TIME"))
{ {
irc_cmd_ctcp_reply(_irc_session, the_nick, [[NSDate dateWithTimeIntervalSinceNow:0] descriptionWithCalendarFormat:@"TIME %a %b %e %H:%M:%S %Z %Y" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]].UTF8String);
irc_cmd_ctcp_reply(_irc_session, the_nick, [[[NSDate dateWithTimeIntervalSinceNow:0] descriptionWithCalendarFormat:@"TIME %a %b %e %H:%M:%S %Z %Y" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]] cStringUsingEncoding:_encoding]);
} }
else else
{ {
char* request_type = strtok(request_string, " "); char* request_type = strtok(request_string, " ");
char* request_body = strtok(NULL, " " ); char* request_body = strtok(NULL, " " );
[_delegate CTCPRequestReceived:[NSData dataWithBytes:request_body length:strlen(request_body) + 1] ofType:[NSData dataWithBytes:request_type length:strlen(request_type) + 1] fromUser:nick];
NSData* requestTypeData = [NSData dataWithBytes:request_body length:strlen(request_body) + 1];
NSData* requestBodyData = [NSData dataWithBytes:request_type length:strlen(request_type) + 1];
[_delegate CTCPRequestReceived:requestBodyData.SA_dataWithTerminatedCString ofType:requestTypeData.SA_dataWithTerminatedCString fromUser:nick];
free(request_string); free(request_string);
} }


- (void)CTCPReplyReceived:(NSData *)reply fromUser:(NSString *)nick - (void)CTCPReplyReceived:(NSData *)reply fromUser:(NSString *)nick
{ {
[_delegate CTCPReplyReceived:reply fromUser:nick];
[_delegate CTCPReplyReceived:reply.SA_dataWithTerminatedCString fromUser:nick];
} }


- (void)CTCPActionPerformed:(NSData *)action byUser:(NSString *)nick atTarget:(NSData *)target - (void)CTCPActionPerformed:(NSData *)action byUser:(NSString *)nick atTarget:(NSData *)target


- (void)unknownEventReceived:(NSData *)event from:(NSString *)origin params:(NSArray *)params - (void)unknownEventReceived:(NSData *)event from:(NSString *)origin params:(NSArray *)params
{ {
[_delegate unknownEventReceived:event from:origin params:params];
[_delegate unknownEventReceived:event.SA_dataWithTerminatedCString from:origin params:params];
} }


-(void)numericEventReceived:(NSUInteger)event from:(NSString *)origin params:(NSArray *)params -(void)numericEventReceived:(NSUInteger)event from:(NSString *)origin params:(NSArray *)params
static void onQuit(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count) static void onQuit(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{ {
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *reason = nil; NSData *reason = nil;
if(count > 0) if(count > 0)
{ {
reason = [[NSData alloc] initWithBytes:params[0] length:strlen(params[0]) + 1];
reason = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];
}
else
{
reason = [NSData dataWithBytes:"\0" length:1];
} }


[clientSession userQuit:nick withReason:reason]; [clientSession userQuit:nick withReason:reason];
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1]; NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];

NSData *reason = nil; NSData *reason = nil;
if (count > 1) if (count > 1)
{ {
reason = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; reason = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
reason = [NSData dataWithBytes:"\0" length:1];
}
[clientSession userParted:nick channel:channelName withReason:reason]; [clientSession userParted:nick channel:channelName withReason:reason];
} }
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1]; NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];
NSString *mode = @(params[1]); NSString *mode = @(params[1]);

NSString *modeParams = nil; NSString *modeParams = nil;
if (count > 2) if (count > 2)
{ {
modeParams = @(params[2]); modeParams = @(params[2]);
} }
else
{
modeParams = @"";
}
[clientSession modeSet:mode withParams:modeParams forChannel:channelName by:nick]; [clientSession modeSet:mode withParams:modeParams forChannel:channelName by:nick];
} }
{ {
topic = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; topic = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
topic = [NSData dataWithBytes:"\0" length:1];
}
[clientSession topicSet:topic forChannel:channelName by:nick]; [clientSession topicSet:topic forChannel:channelName by:nick];
} }
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *byNick = @(origin); NSString *byNick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1]; NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];

NSString *nick = nil; NSString *nick = nil;
NSData *reason = nil;
if (count > 1) if (count > 1)
{ {
nick = @(params[1]); nick = @(params[1]);
} }
NSData *reason = nil;
if (count > 2) if (count > 2)
{ {
reason = [NSData dataWithBytes:params[2] length:strlen(params[2]) + 1]; reason = [NSData dataWithBytes:params[2] length:strlen(params[2]) + 1];
} }
else
{
reason = [NSData dataWithBytes:"\0" length:1];
}
[clientSession userKicked:nick fromChannel:channelName by:byNick withReason:reason]; [clientSession userKicked:nick fromChannel:channelName by:byNick withReason:reason];
} }
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1]; NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];
NSData *message = nil;
NSData *message = nil;
if (count > 1) if (count > 1)
{ {
message = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; message = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
message = [NSData dataWithBytes:"\0" length:1];
}


[clientSession messageSent:message toChannel:channelName byUser:nick]; [clientSession messageSent:message toChannel:channelName byUser:nick];
} }
{ {
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *message = nil; NSData *message = nil;

if (count > 1) if (count > 1)
{ {
message = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; message = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
message = [NSData dataWithBytes:"\0" length:1];
}
[clientSession privateMessageReceived:message fromUser:nick]; [clientSession privateMessageReceived:message fromUser:nick];
} }
{ {
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *notice = nil;
NSData *notice = nil;
if (count > 1) if (count > 1)
{ {
notice = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; notice = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
notice = [NSData dataWithBytes:"\0" length:1];
}
[clientSession privateNoticeReceived:notice fromUser:nick]; [clientSession privateNoticeReceived:notice fromUser:nick];
} }
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin); NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1]; NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0]) + 1];
NSData *notice = nil;
NSData *notice = nil;
if (count > 1) if (count > 1)
{ {
notice = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1]; notice = [NSData dataWithBytes:params[1] length:strlen(params[1]) + 1];
} }
else
{
notice = [NSData dataWithBytes:"\0" length:1];
}


[clientSession noticeSent:notice toChannel:channelName byUser:nick]; [clientSession noticeSent:notice toChannel:channelName byUser:nick];
} }
static void onUnknownEvent(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count) static void onUnknownEvent(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{ {
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session); IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSData *eventString = [NSData dataWithBytes:event length:strlen(event) + 1];
NSString *sender = nil;
NSData *eventData = [NSData dataWithBytes:event length:strlen(event) + 1];
NSString *originString = nil;
if (origin != NULL) if (origin != NULL)
sender = @(origin);
{
originString = @(origin);
}
NSMutableArray *paramsArray = [[NSMutableArray alloc] init]; NSMutableArray *paramsArray = [[NSMutableArray alloc] init];
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{
[paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i]) + 1]]; [paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i]) + 1]];
}
[clientSession unknownEventReceived:eventString from:sender params:[paramsArray copy]];
[clientSession unknownEventReceived:eventData from:originString params:paramsArray];
} }


/*! /*!
NSString *sender = @(origin); NSString *sender = @(origin);
NSMutableArray *paramsArray = [[NSMutableArray alloc] init]; NSMutableArray *paramsArray = [[NSMutableArray alloc] init];
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{
[paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i]) + 1]]; [paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i]) + 1]];
}
[clientSession numericEventReceived:eventNumber from:sender params:[paramsArray copy]];
[clientSession numericEventReceived:eventNumber from:sender params:paramsArray];
} }

Laden…
Annuleren
Opslaan