From 0cd2322d48c8889e47a0d5ee635503c19cb6fb2b Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 7 Aug 2009 12:26:31 +0200 Subject: piano: Check (m|c|re)alloc return value --- libpiano/src/crypt.c | 41 ++++++++++----- libpiano/src/http.c | 4 ++ libpiano/src/main.c | 16 ++++-- libpiano/src/piano.h | 2 +- libpiano/src/xml.c | 143 ++++++++++++++++++++++++++++++++++++--------------- 5 files changed, 147 insertions(+), 59 deletions(-) diff --git a/libpiano/src/crypt.c b/libpiano/src/crypt.c index 67e2467..9b21516 100644 --- a/libpiano/src/crypt.c +++ b/libpiano/src/crypt.c @@ -38,20 +38,24 @@ THE SOFTWARE. /* decrypt hex-encoded, blowfish-crypted string: decode 2 hex-encoded blocks, * decrypt, byteswap * @param hex string - * @return decrypted string + * @return decrypted string or NULL */ #define INITIAL_SHIFT 28 #define SHIFT_DEC 4 unsigned char *PianoDecryptString (const unsigned char *strInput) { /* hex-decode => strlen/2 + null-byte */ - uint32_t *iDecrypt = calloc (strlen ((char *) strInput)/2/sizeof (*iDecrypt)+1, sizeof (*iDecrypt)); - unsigned char *strDecrypted = (unsigned char *) iDecrypt; - unsigned char shift = INITIAL_SHIFT; - unsigned char intsDecoded = 0; - unsigned char j; + uint32_t *iDecrypt; + unsigned char *strDecrypted; + unsigned char shift = INITIAL_SHIFT, intsDecoded = 0, j; /* blowfish blocks, 32-bit */ uint32_t f, l, r, lrExchange; + if ((iDecrypt = calloc (strlen ((char *) strInput)/2/sizeof (*iDecrypt)+1, + sizeof (*iDecrypt))) == NULL) { + return NULL; + } + strDecrypted = (unsigned char *) iDecrypt; + while (*strInput != '\0') { /* hex-decode string */ if (*strInput >= '0' && *strInput <= '9') { @@ -115,20 +119,29 @@ unsigned char *PianoEncryptString (const unsigned char *strInput) { const size_t strInputN = strlen ((char *) strInput); /* num of 64-bit blocks, rounded to next block */ size_t blockN = strInputN / 8 + 1; - uint32_t *blockInput = calloc (blockN*2, sizeof (*blockInput)); - uint32_t *blockPtr = blockInput; - /* encryption blocks */ - uint32_t f, lrExchange; - register uint32_t l, r; + uint32_t *blockInput, *blockPtr; /* output string */ - unsigned char *strHex = calloc (blockN*8*2 + 1, sizeof (*strHex)); - unsigned char *hexPtr = strHex; + unsigned char *strHex, *hexPtr; const char *hexmap = "0123456789abcdef"; - size_t i; + + if ((blockInput = calloc (blockN*2, sizeof (*blockInput))) == NULL) { + return NULL; + } + blockPtr = blockInput; + + if ((strHex = calloc (blockN*8*2 + 1, sizeof (*strHex))) == NULL) { + return NULL; + } + hexPtr = strHex; memcpy (blockInput, strInput, strInputN); while (blockN > 0) { + /* encryption blocks */ + uint32_t f, lrExchange; + register uint32_t l, r; + int i; + l = byteswap32 (*blockPtr); r = byteswap32 (*(blockPtr+1)); diff --git a/libpiano/src/http.c b/libpiano/src/http.c index d33a4e5..f21b839 100644 --- a/libpiano/src/http.c +++ b/libpiano/src/http.c @@ -43,6 +43,10 @@ PianoReturn_t PianoHttpPost (WaitressHandle_t *waith, const char *postData, PianoReturn_t pRet = PIANO_RET_NET_ERROR; char *reqPostData = PianoEncryptString (postData); + if (reqPostData == NULL) { + return PIANO_RET_OUT_OF_MEMORY; + } + waith->extraHeaders = "Content-Type: text/xml\r\n"; waith->postData = reqPostData; waith->method = WAITRESS_METHOD_POST; diff --git a/libpiano/src/main.c b/libpiano/src/main.c index 01e055b..b3bcab8 100644 --- a/libpiano/src/main.c +++ b/libpiano/src/main.c @@ -390,7 +390,10 @@ PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station, char *urlencodedNewName, *xmlencodedNewName; PianoReturn_t ret = PIANO_RET_ERR; - xmlencodedNewName = PianoXmlEncodeString (newName); + if ((xmlencodedNewName = PianoXmlEncodeString (newName)) == NULL) { + return PIANO_RET_OUT_OF_MEMORY; + } + snprintf (xmlSendBuf, sizeof (xmlSendBuf), "" "station.setStationName" "%li" @@ -479,7 +482,10 @@ PianoReturn_t PianoSearchMusic (PianoHandle_t *ph, char *xmlencodedSearchStr, *urlencodedSearchStr; PianoReturn_t ret; - xmlencodedSearchStr = PianoXmlEncodeString (searchStr); + if ((xmlencodedSearchStr = PianoXmlEncodeString (searchStr)) == NULL) { + return PIANO_RET_OUT_OF_MEMORY; + } + snprintf (xmlSendBuf, sizeof (xmlSendBuf), "" "music.search" "%li" @@ -810,7 +816,11 @@ const char *PianoErrorToStr (PianoReturn_t ret) { break; case PIANO_RET_STATION_NONEXISTENT: - return "Station does not exist"; + return "Station does not exist."; + break; + + case PIANO_RET_OUT_OF_MEMORY: + return "Out of memory."; break; default: diff --git a/libpiano/src/piano.h b/libpiano/src/piano.h index caee1b7..2910e99 100644 --- a/libpiano/src/piano.h +++ b/libpiano/src/piano.h @@ -104,7 +104,7 @@ typedef enum {PIANO_RET_OK, PIANO_RET_ERR, PIANO_RET_XML_INVALID, PIANO_RET_NET_ERROR, PIANO_RET_NOT_AUTHORIZED, PIANO_RET_PROTOCOL_INCOMPATIBLE, PIANO_RET_READONLY_MODE, PIANO_RET_STATION_CODE_INVALID, PIANO_RET_IP_REJECTED, - PIANO_RET_STATION_NONEXISTENT} PianoReturn_t; + PIANO_RET_STATION_NONEXISTENT, PIANO_RET_OUT_OF_MEMORY} PianoReturn_t; void PianoInit (PianoHandle_t *); void PianoDestroy (PianoHandle_t *); diff --git a/libpiano/src/xml.c b/libpiano/src/xml.c index 463caa7..2cc519f 100644 --- a/libpiano/src/xml.c +++ b/libpiano/src/xml.c @@ -45,7 +45,7 @@ static void PianoXmlIsFaultCb (const char *key, const ezxml_t value, void *data) { PianoReturn_t *ret = data; char *valueStr = PianoXmlGetNodeText (value); - char *matchStart, *matchEnd, *matchStr; + char *matchStart, *matchEnd; if (strcmp ("faultString", key) == 0) { *ret = PIANO_RET_ERR; @@ -56,36 +56,34 @@ static void PianoXmlIsFaultCb (const char *key, const ezxml_t value, if ((matchStart = strchr (valueStr, '|')) != NULL) { if ((matchStart = strchr (matchStart+1, '|')) != NULL) { if ((matchEnd = strchr (matchStart+1, '|')) != NULL) { - matchStr = calloc (matchEnd - (matchStart+1)+1, - sizeof (*matchStr)); - memcpy (matchStr, matchStart+1, matchEnd - - (matchStart+1)); + /* changes text in xml node, but we don't care... */ + *matchEnd = '\0'; + ++matchStart; /* translate to our error message system */ - if (strcmp ("AUTH_INVALID_TOKEN", matchStr) == 0) { + if (strcmp ("AUTH_INVALID_TOKEN", matchStart) == 0) { *ret = PIANO_RET_AUTH_TOKEN_INVALID; } else if (strcmp ("AUTH_INVALID_USERNAME_PASSWORD", - matchStr) == 0) { + matchStart) == 0) { *ret = PIANO_RET_AUTH_USER_PASSWORD_INVALID; } else if (strcmp ("LISTENER_NOT_AUTHORIZED", - matchStr) == 0) { + matchStart) == 0) { *ret = PIANO_RET_NOT_AUTHORIZED; } else if (strcmp ("INCOMPATIBLE_VERSION", - matchStr) == 0) { + matchStart) == 0) { *ret = PIANO_RET_PROTOCOL_INCOMPATIBLE; - } else if (strcmp ("READONLY_MODE", matchStr) == 0) { + } else if (strcmp ("READONLY_MODE", matchStart) == 0) { *ret = PIANO_RET_READONLY_MODE; } else if (strcmp ("STATION_CODE_INVALID", - matchStr) == 0) { + matchStart) == 0) { *ret = PIANO_RET_STATION_CODE_INVALID; } else if (strcmp ("STATION_DOES_NOT_EXIST", - matchStr) == 0) { + matchStart) == 0) { *ret = PIANO_RET_STATION_NONEXISTENT; } else { *ret = PIANO_RET_ERR; printf (PACKAGE ": Unknown error %s in %s\n", - matchStr, valueStr); + matchStart, valueStr); } - PianoFree (matchStr, 0); } } } @@ -232,18 +230,24 @@ static void PianoXmlParsePlaylistCb (const char *key, const ezxml_t value, if (strcmp ("audioURL", key) == 0) { /* last 48 chars of audioUrl are encrypted, but they put the key - * into the door's lock; dumb pandora... */ + * into the door's lock... */ const char urlTailN = 48; const size_t valueStrN = strlen (valueStr); char *urlTail = NULL, *urlTailCrypted = &valueStr[valueStrN - urlTailN]; - urlTail = PianoDecryptString (urlTailCrypted); - song->audioUrl = calloc (valueStrN + 1, sizeof (*song->audioUrl)); - memcpy (song->audioUrl, valueStr, valueStrN - urlTailN); - /* FIXME: the key seems to be broken... so ignore 8 x 0x08 postfix; - * urlTailN/2 because the encrypted hex string is now decoded */ - memcpy (&song->audioUrl[valueStrN - urlTailN], urlTail, urlTailN/2 - 8); - PianoFree (urlTail, urlTailN/2); + + if ((urlTail = PianoDecryptString (urlTailCrypted)) != NULL) { + if ((song->audioUrl = calloc (valueStrN + 1, + sizeof (*song->audioUrl))) != NULL) { + memcpy (song->audioUrl, valueStr, valueStrN - urlTailN); + /* FIXME: the key seems to be broken... so ignore 8 x 0x08 + * postfix; urlTailN/2 because the encrypted hex string is now + * decoded */ + memcpy (&song->audioUrl[valueStrN - urlTailN], urlTail, + urlTailN/2 - 8); + } + PianoFree (urlTail, urlTailN/2); + } } else if (strcmp ("artistSummary", key) == 0) { song->artist = strdup (valueStr); } else if (strcmp ("musicId", key) == 0) { @@ -315,18 +319,32 @@ static void PianoXmlParseQuickMixStationsCb (const char *key, const ezxml_t valu curNode; curNode = curNode->next) { idsN++; if (ids == NULL) { - ids = calloc (idsN, sizeof (*ids)); + if ((ids = calloc (idsN, sizeof (*ids))) == NULL) { + *retIds = NULL; + return; + } } else { - ids = realloc (ids, idsN * sizeof (*ids)); + /* FIXME: memory leak (on failure) */ + if ((ids = realloc (ids, idsN * sizeof (*ids))) == NULL) { + *retIds = NULL; + return; + } } ids[idsN-1] = strdup (PianoXmlGetNodeText (curNode)); } /* append NULL: list ends here */ idsN++; + /* FIXME: copy&waste */ if (ids == NULL) { - ids = calloc (idsN, sizeof (*ids)); + if ((ids = calloc (idsN, sizeof (*ids))) == NULL) { + *retIds = NULL; + return; + } } else { - ids = realloc (ids, idsN * sizeof (*ids)); + if ((ids = realloc (ids, idsN * sizeof (*ids))) == NULL) { + *retIds = NULL; + return; + } } ids[idsN-1] = NULL; } @@ -352,9 +370,16 @@ PianoReturn_t PianoXmlParseStations (PianoHandle_t *ph, char *xml) { for (dataNode = ezxml_child (dataNode, "value"); dataNode; dataNode = dataNode->next) { - PianoStation_t *tmpStation = calloc (1, sizeof (*tmpStation)); + PianoStation_t *tmpStation; + + if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) { + ezxml_free (xmlDoc); + return PIANO_RET_OUT_OF_MEMORY; + } + PianoXmlStructParser (ezxml_child (dataNode, "struct"), PianoXmlParseStationsCb, tmpStation); + /* get stations selected for quickmix */ if (tmpStation->isQuickMix) { PianoXmlStructParser (ezxml_child (dataNode, "struct"), @@ -406,7 +431,11 @@ PianoReturn_t PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) { } dataNode = ezxml_get (xmlDoc, "params", 0, "param", 0, "value", 0, "struct", -1); - tmpStation = calloc (1, sizeof (*tmpStation)); + + if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) { + ezxml_free (xmlDoc); + return PIANO_RET_OUT_OF_MEMORY; + } PianoXmlStructParser (dataNode, PianoXmlParseStationsCb, tmpStation); /* FIXME: copy & waste */ /* start new linked list or append */ @@ -465,7 +494,13 @@ PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) { for (dataNode = ezxml_child (dataNode, "value"); dataNode; dataNode = dataNode->next) { - PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong)); + PianoSong_t *tmpSong; + + if ((tmpSong = calloc (1, sizeof (*tmpSong))) == NULL) { + ezxml_free (xmlDoc); + return PIANO_RET_OUT_OF_MEMORY; + } + PianoXmlStructParser (ezxml_child (dataNode, "struct"), PianoXmlParsePlaylistCb, tmpSong); /* begin linked list or append */ @@ -538,7 +573,13 @@ static void PianoXmlParseSearchCb (const char *key, const ezxml_t value, /* skip */ for (curNode = ezxml_child (ezxml_get (value, "array", 0, "data", -1), "value"); curNode; curNode = curNode->next) { - PianoArtist_t *artist = calloc (1, sizeof (*artist)); + PianoArtist_t *artist; + + if ((artist = calloc (1, sizeof (*artist))) == NULL) { + /* fail silently */ + break; + } + memset (artist, 0, sizeof (*artist)); PianoXmlStructParser (ezxml_child (curNode, "struct"), @@ -559,7 +600,13 @@ static void PianoXmlParseSearchCb (const char *key, const ezxml_t value, for (curNode = ezxml_child (ezxml_get (value, "array", 0, "data", -1), "value"); curNode; curNode = curNode->next) { /* FIXME: copy & waste */ - PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong)); + PianoSong_t *tmpSong; + + if ((tmpSong = calloc (1, sizeof (*tmpSong))) == NULL) { + /* fail silently */ + break; + } + PianoXmlStructParser (ezxml_child (curNode, "struct"), PianoXmlParsePlaylistCb, tmpSong); /* begin linked list or append */ @@ -603,15 +650,18 @@ PianoReturn_t PianoXmlParseSearch (char *xml, /* encode reserved xml chars * TODO: remove and use ezxml_ampencode * @param encode this - * @return encoded string + * @return encoded string or NULL */ char *PianoXmlEncodeString (const char *s) { char *replacements[] = {"&&", "''", "\""", "<<", ">>", NULL}; - char **r; - char *sOut = calloc (strlen (s) * 5 + 1, sizeof (*sOut)), - *sOutCurr = sOut; - char found; + char **r, *sOut, *sOutCurr, found; + + if ((sOut = calloc (strlen (s) * 5 + 1, sizeof (*sOut))) == NULL) { + return NULL; + } + + sOutCurr = sOut; while (*s != '\0') { r = replacements; @@ -635,10 +685,8 @@ char *PianoXmlEncodeString (const char *s) { } PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, char *xml) { - ezxml_t xmlDoc, catNode, genreNode; + ezxml_t xmlDoc, catNode; PianoReturn_t ret; - PianoGenreCategory_t *tmpGenreCategory; - PianoStation_t *tmpStation; if ((ret = PianoXmlInitDoc (xml, &xmlDoc)) != PIANO_RET_OK) { return ret; @@ -647,13 +695,26 @@ PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, char *xml) { /* get all nodes */ for (catNode = ezxml_child (xmlDoc, "category"); catNode; catNode = catNode->next) { - tmpGenreCategory = calloc (1, sizeof (*tmpGenreCategory)); + PianoGenreCategory_t *tmpGenreCategory; + ezxml_t genreNode; + + if ((tmpGenreCategory = calloc (1, sizeof (*tmpGenreCategory))) == NULL) { + ezxml_free (xmlDoc); + return PIANO_RET_OUT_OF_MEMORY; + } + tmpGenreCategory->name = strdup (ezxml_attr (catNode, "categoryName")); /* get genre subnodes */ for (genreNode = ezxml_child (catNode, "genre"); genreNode; genreNode = genreNode->next) { - tmpStation = calloc (1, sizeof (*tmpStation)); + PianoStation_t *tmpStation; + + if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) { + ezxml_free (xmlDoc); + return PIANO_RET_OUT_OF_MEMORY; + } + /* get genre attributes */ tmpStation->name = strdup (ezxml_attr (genreNode, "name")); tmpStation->id = strdup (ezxml_attr (genreNode, "stationId")); -- cgit v1.2.3