1818
1919static void mongo_sasl_conn_free (void * data ) {
2020 sasl_conn_t * conn = (sasl_conn_t * ) data ;
21- // Ideally we would use sasl_client_done() but that's only available as of cyrus sasl 2.1.25
22- if (conn ) sasl_done ();
21+ if (conn ) {
22+ sasl_dispose (& conn );
23+ /* We do not set connection to NULL in the Ruby object. */
24+ /* This is probably fine because this method is supposed to be called */
25+ /* when the Ruby object is being garbage collected. */
26+ /* Plus, we don't have the Ruby object reference here to do anything */
27+ /* with it. */
28+ }
2329}
2430
2531static sasl_conn_t * mongo_sasl_context (VALUE self ) {
@@ -104,7 +110,14 @@ static VALUE initialize_challenge(VALUE self) {
104110 }
105111
106112 context = Data_Wrap_Struct (rb_cObject , NULL , mongo_sasl_conn_free , conn );
113+ /* I'm guessing ruby raises on out of memory condition rather than */
114+ /* returns NULL, hence no error checking is needed here? */
115+
116+ /* from now on context owns conn */
117+ /* since mongo_sasl_conn_free cleans up conn, we should NOT call */
118+ /* sasl_dispose any more in this function. */
107119 rb_iv_set (self , "@context" , context );
120+ RB_GC_GUARD (context );
108121
109122 result = sasl_client_start (conn , mechanism_list , NULL , & raw_payload , & raw_payload_len , & mechanism_selected );
110123 if (is_sasl_failure (result )) {
@@ -115,7 +128,9 @@ static VALUE initialize_challenge(VALUE self) {
115128 return Qfalse ;
116129 }
117130
118- result = sasl_encode64 (raw_payload , raw_payload_len , encoded_payload , sizeof (encoded_payload ), & encoded_payload_len );
131+ /* cyrus-sasl considers `outmax` (fourth argument) to include the null */
132+ /* terminator, but this is not documented. Be defensive and exclude it. */
133+ result = sasl_encode64 (raw_payload , raw_payload_len , encoded_payload , sizeof (encoded_payload )- 1 , & encoded_payload_len );
119134 if (is_sasl_failure (result )) {
120135 return Qfalse ;
121136 }
@@ -135,17 +150,17 @@ static VALUE evaluate_challenge(VALUE self, VALUE rb_payload) {
135150 step_payload = RSTRING_PTR (rb_payload );
136151 step_payload_len = (int )RSTRING_LEN (rb_payload );
137152
138- result = sasl_decode64 (step_payload , step_payload_len , base_payload , sizeof (base_payload ), & base_payload_len );
153+ result = sasl_decode64 (step_payload , step_payload_len , base_payload , sizeof (base_payload )- 1 , & base_payload_len );
139154 if (is_sasl_failure (result )) {
140155 return Qfalse ;
141156 }
142157
143158 result = sasl_client_step (conn , base_payload , base_payload_len , NULL , & out , & outlen );
144159 if (is_sasl_failure (result )) {
145- return Qfalse ;
160+ return Qfalse ;
146161 }
147162
148- result = sasl_encode64 (out , outlen , payload , sizeof (payload ), & payload_len );
163+ result = sasl_encode64 (out , outlen , payload , sizeof (payload )- 1 , & payload_len );
149164 if (is_sasl_failure (result )) {
150165 return Qfalse ;
151166 }
0 commit comments