-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixing other potential memory corruption #155
Conversation
@@ -23,7 +23,7 @@ | |||
|
|||
// Get from console | |||
// ================================================= | |||
#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow | |||
#define AWS_IOT_MQTT_HOST "a3qggb6vsdlf5s.iot.us-west-2.amazonaws.com" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Endpoint should be removed. Changes to this file shouldn't be committed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, fixed
src/aws_iot_mqtt_client.c
Outdated
rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); | ||
} | ||
|
||
if ((&(pClient->clientData.state_change_mutex) != NULL)&&(rc == SUCCESS)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should check if tls_read_mutex
isn't NULL
.
How about also setting pClient->clientData.tls_read_mutex
to NULL
after destroying it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a bug, it is a structure.
src/aws_iot_mqtt_client.c
Outdated
rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); | ||
} | ||
|
||
if ((&(pClient->clientData.state_change_mutex) != NULL)&&(rc == SUCCESS)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should check if tls_write_mutex
isn't NULL
.
How about also setting pClient->clientData.tls_write_mutex
to NULL
after destroying it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a bug, it is a structure.
src/aws_iot_mqtt_client.c
Outdated
#ifdef _ENABLE_THREAD_SUPPORT_ | ||
if ((&(pClient->clientData.state_change_mutex) != NULL)&&(rc == SUCCESS)) | ||
{ | ||
rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about also setting pClient->clientData.state_change_mutex
to NULL
after destroying it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure about handling in this way.
(&(pClient->clientData.state_change_mutex) != NULL)
checks if the address of variable pClient->clientData.state_change_mutex
is not NULL
.
Then this address is passed to aws_iot_thread_mutex_destroy()
by value; the function can free the content, but cannot modify the parameter passed by value (that is the address).
Even setting pClient->clientData.state_change_mutex
to NULL
(which I think it's a good idea), its address is not NULL.
And so calling aws_iot_mqtt_free()
one more time the condition (&(pClient->clientData.state_change_mutex) != NULL)
is true
and so aws_iot_thread_mutex_destroy()
would be called ahain.
Is this the expected beahvior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it is a bug, checking NULL is pointless, it is a structure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems there is not need to check, destroy will set it to an invalid value so subsequent call will return EINVALID
src/aws_iot_shadow_json.c
Outdated
@@ -424,13 +462,13 @@ bool isReceivedJsonValid(const char *pJsonDocument) { | |||
return true; | |||
} | |||
|
|||
bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken) { | |||
bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize) { | |||
int32_t tokenCount, i; | |||
uint8_t length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure uint8_t
(up to 255) is always sufficient? How about size_t
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still uint8_t
in the latest version?
ret_val = isReceivedJsonValid(getRequestJson, TEST_JSON_SIZE); | ||
CHECK_EQUAL_C_INT(true, ret_val); | ||
|
||
IOT_DEBUG("-->Success - sReceivedJsonValid"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong test name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
bool ret_val; | ||
char getRequestJson[TEST_JSON_SIZE]; | ||
|
||
IOT_DEBUG("-->Running Shadow Action Tests - sReceivedJsonValid \n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong test name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still sReceivedJsonValid
in the latest version?
ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); | ||
CHECK_EQUAL_C_INT(true, ret_val); | ||
|
||
IOT_DEBUG("-->Success - getAndDeleteRequest"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong test name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
Can you also change aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c Lines 207 to 221 in ba30f68
In |
Ok, I will change that. |
src/aws_iot_mqtt_client.c
Outdated
rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); | ||
} | ||
|
||
if (rc == SUCCESS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should still attempt to destroy mutexes, even if the previous call to aws_iot_thread_mutex_destroy
failed. We could also print a debug message if a call to aws_iot_thread_mutex_destroy
fails.
FUNC_EXIT_RC(rc); | ||
} | ||
rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); | ||
if(SUCCESS != rc) { | ||
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); | ||
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); | ||
FUNC_EXIT_RC(rc); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 263 also contains an exit on failure, should also destroy mutexes there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I agree totally with that process. The mqtt free should be called after init anyway. I think we are bringing complexity when not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if mqtt_init
returns something other than SUCCESS
, users may not know they need to call mqtt_free
. I think it makes sense for init
to clean everything up if it fails.
Deleting as much mutexes as possible
adding destroy at the end of function
{ | ||
rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); | ||
}else{ | ||
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should destroy tls_write_mutex
.
Also, is it necessary to re-assign rc
? Seems we could just do the following to clean everything up.
if(rc == SUCCESS) /* Check not NULL_VALUE_ERROR. */
{
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex));
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex));
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though of that but it will not work unless you refactor the function because it has exit points everywhere
FUNC_EXIT_RC(rc); | ||
} | ||
rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); | ||
if(SUCCESS != rc) { | ||
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); | ||
(void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); | ||
FUNC_EXIT_RC(rc); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if mqtt_init
returns something other than SUCCESS
, users may not know they need to call mqtt_free
. I think it makes sense for init
to clean everything up if it fails.
Fix a forgotten statement
Fixing unit tests
Fixing auto reconnect
Display wrong message when received
Changed string
Fixed dereferencing void pointer
Fix compilation error
Added thing identification to test
Extended string
use strtok_s for thread safety
Fix compilation error
Fix bugs from coverity
Cosmetic changes from review comment
Fixing other potential memory corruption bugs.
Also added a function to free up mutexes created by mqtt init and shadow init
Passed unit tests and integration tests